!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !MODULE: gckpp_HetRates
!
! !DESCRIPTION: FlexChem module for heterogeneous chemistry, via KPP.
!\\
!\\
! !INTERFACE:

MODULE GCKPP_HETRATES
!
! !USES:
!
  USE CMN_FJX_MOD,        ONLY : NDUST
  USE CMN_FJX_MOD,        ONLY : NAER
  USE CMN_SIZE_MOD,       ONLY : LLSTRAT
  USE ERROR_MOD,          ONLY : ERROR_STOP
  USE ERROR_MOD,          ONLY : GEOS_CHEM_STOP
  USE ERROR_MOD,          ONLY : IS_SAFE_DIV, SAFE_DIV
  USE gckpp_Precision
  USE gckpp_Parameters
  USE gckpp_Global,       ONLY : HET
  USE State_Chm_Mod,      ONLY : ChmState
  USE State_Chm_Mod,      ONLY : Ind_
  USE State_Diag_Mod,     ONLY : DgnState
  USE State_Met_Mod,      ONLY : MetState
  USE Input_Opt_Mod,      ONLY : OptInput
  USE PhysConstants,      ONLY : AVO, RGASLATM, CONSVAP
  USE Precision_Mod,      ONLY : fp

  IMPLICIT NONE
  PRIVATE
!
! !PUBLIC MEMBER FUNCTIONS:
!
  PUBLIC  :: SET_HET
!
! !PRIVATE MEMBER FUNCTIONS:
!
  ! These functions are used for all mechanisms
  PRIVATE :: HetNO3
  PRIVATE :: HetNO2
  PRIVATE :: HetHO2
  PRIVATE :: HetGLYX
  PRIVATE :: HetMGLY
  PRIVATE :: HetIEPOX
  PRIVATE :: HetIMAE
  PRIVATE :: HetLVOC
  PRIVATE :: HetISOPND
  PRIVATE :: HetISOPNB
  PRIVATE :: HetMACRN
  PRIVATE :: HetMVKN
  PRIVATE :: HetR4N2
  PRIVATE :: HetISN1OG
  PRIVATE :: HetDHDN
  PRIVATE :: HetMONITS
  PRIVATE :: HetMONITU
  PRIVATE :: HetHONIT
  PRIVATE :: HetIONITA
  PRIVATE :: HetMONITA
  PRIVATE :: HetHBr
  PRIVATE :: HetN2O5
  PRIVATE :: N2O5
  PRIVATE :: HO2

  ! New iodine heterogeneous chemistry
  PRIVATE :: HETIUptake
  PRIVATE :: HETIXCycleSSA      !xnw modified

  ! These are the new Br/Cl functions from J. Schmidt
  PRIVATE :: HETBrNO3_JS
  PRIVATE :: HETClNO3_JS
  PRIVATE :: HETHOBr_HBr_JS     !xnw modified
  PRIVATE :: HETHOBr_HCl_JS     !xnw modified
  PRIVATE :: HETClNO3_HBr_JS    !xnw modified
  PRIVATE :: HETO3_HBr_JS       !xnw modified
  PRIVATE :: HETHOBr_SS_JS      !xnw modified
  PRIVATE :: HETClNO3_SS_JS     !xnw modified
  PRIVATE :: HETO3_SS_JS
  PRIVATE :: HETHXUptake_JS
  PRIVATE :: HETN2O5_SS         !xnw modified
  PRIVATE :: HETHOCl_SS         !xnw
  PRIVATE :: HETHOBr_TCld       !xnw    
  PRIVATE :: HETClNO3_TCld      !xnw
  PRIVATE :: HETClNO2_TCld      !xnw
  PRIVATE :: HETOH              !xnw
  PRIVATE :: HETClNO2           !xnw
  PRIVATE :: HetNO3_Cl          !xnw

  ! New subroutines required by the JS functions
  PRIVATE :: Gamma_O3_Br
  PRIVATE :: Gamma_HX_Uptake
  PRIVATE :: Coth
  PRIVATE :: ReactoDiff_Corr
  PRIVATE :: Gamma_HOBr_CLD     !qjc
  PRIVATE :: Gamma_HOBr_AER     !qjc
  PRIVATE :: Gamma_ClNO3_AER    !xnw
  PRIVATE :: Gamma_N2O5_Cl      !xnw
  PRIVATE :: Gamma_ClNO2        !xnw
  PRIVATE :: Gamma_HOCl         !xnw
  PRIVATE :: Gamma_NO3         !xnw

  ! These are formerly strat-only reactions extended to take place in the
  ! troposphere on sulfate aerosol
  PRIVATE :: HETClNO3_HCl       !xnw modified
  PRIVATE :: HETHOCl_HBr
  PRIVATE :: HETHOCl_HCl    
  PRIVATE :: HETBrNO3_HCl   
  PRIVATE :: HETN2O5_HCl    

  ! These are subfunctions to calculate rates on/in clouds and SSA
  PRIVATE :: CLD_PARAMS
  PRIVATE :: GET_HALIDE_CLDConc    !xnw
  Private :: Get_Halide_SSAConc    !xnw modified
  PRIVATE :: COMPUTE_L2G_LOCAL
  PRIVATE :: CLD1K_XNO3
  PRIVATE :: EPOXUPTK
  PRIVATE :: FCRO2HO2
  PRIVATE :: FYHORO
  PRIVATE :: FYRNO3
  PRIVATE :: ARSL1K
  PRIVATE :: kIIR1Ltd
  PRIVATE :: kIIR1R2L
!
! !PRIVATE DATA MEMBERS:
!
  ! Scalars
  INTEGER  :: NAERO
  LOGICAL  :: NATSURFACE,   PSCBOX,    STRATBOX
  REAL(fp) :: TEMPK,        RELHUM,    SUNCOS,  SPC_SO4
  REAL(fp) :: SPC_NIT,      GAMMA_HO2, XTEMP,   XDENA
  REAL(fp) :: QLIQ,         QICE,      SPC_fCl
  REAL(fp) :: SPC_cCl,      SPC_NITs
  REAL(fp) :: H_PLUS,       MSO4,      MNO3,    MHSO4
  REAL(fp) :: MW_HO2,       MW_NO2,    MW_NO3
  REAL(fp) :: MW_N2O5,      MW_GLYX,   MW_MGLY
  REAL(fp) :: MW_IEPOXA,    MW_IEPOXB, MW_IEPOXD
  REAL(fp) :: MW_IMAE,      MW_LVOC,   MW_ISN1OG
  REAL(fp) :: MW_ISOPND,    MW_ISOPNB, MW_MACRN
  REAL(fp) :: MW_MVKN,      MW_R4N2,   MW_DHDN
  REAL(fp) :: MW_MONITS,    MW_MONITU, MW_HONIT
  REAL(fp) :: MW_IONITA,    MW_MONITA, MW_BrNO3
  REAL(fp) :: MW_HOBr,      MW_HBr,    MW_ClNO3
  REAL(fp) :: MW_HOCl,      MW_HI,     MW_HOI
  REAL(fp) :: MW_I2O2,      MW_I2O3,   MW_I2O4
  REAL(fp) :: MW_IONO,      MW_IONO2,  MW_OH
  REAL(fp) :: HSO3conc_Cld, SO3conc_Cld, fupdateHOBr
  REAL(fp) :: AClAREA,      AClRADI   !xnw
  REAL(fp) :: nitConc_SALA, nitConc_SALC  

  ! Arrays
  REAL(fp) :: SCF2(3)
  REAL(fp) :: XAREA(25)
  REAL(fp) :: XRADI(25)
  REAL(fp) :: KHETI_SLA(11)
  REAL(fp) :: AWATER(2)

!$OMP THREADPRIVATE( NAERO,        NATSURFACE, PSCBOX,   STRATBOX )
!$OMP THREADPRIVATE( TEMPK,        RELHUM,     SPC_NIT,  SPC_SO4  )
!$OMP THREADPRIVATE( SPC_fCl,      SPC_cCl,    SPC_NITs, AWATER   )
!$OMP THREADPRIVATE( GAMMA_HO2,    XTEMP,      XDENA,    QLIQ     )
!$OMP THREADPRIVATE( QICE,         SCF2,       XAREA,    XRADI    )
!$OMP THREADPRIVATE( KHETI_SLA,    SUNCOS,   AClAREA,  AClRADI    )
!$OMP THREADPRIVATE( H_PLUS,       MSO4,       MNO3,     MHSO4    )
!$OMP THREADPRIVATE( HSO3conc_Cld, SO3conc_Cld, fupdateHOBr       )
!
! !DEFINED PARAMETERS:
!
  REAL(fp), PARAMETER :: HetMinLife = 1.e-3_fp

  ! Critical RH for uptake of GLYX, MGLYX, and GLYC:
  REAL(fp), PARAMETER :: CRITRH = 35.0e+0_fp

  ! Effective Henry's Law constant of IEPOX for reactive
  ! uptake to aqueous aerosols (M/atm)
  REAL(fp), PARAMETER :: HSTAR_EPOX = 5.0e+6_fp
!
! !REMARKS:
!  Need 
!  - TOTAREA (previously used for archiving N2O5 hydrolysis in the planeflight
!             diagnostic only)
!  - Air NUM. DENSITY
!  - TEMPERATURE
!  - Aerosol Surface Area
!  - Aerosol Type
!  - Gamma (XSTKCF; sticking factor)
!  - ARR
!  - Species num density (mcl cm-3)
!  - Continental PBL or no?
!  - In stratosphere or no?
!  - Reaction index (e.g. NK1HBr, NK2HBr)
!
!  According to S. Eastham, we should also include
!  cloud and ice area explicitly, in addition to
!  aerosol area
!
! !REFERENCES:
!  Eastham et al., Development and evaluation of the unified tropospheric-
!    stratospheric chemistry extension (UCX) for the global chemistry-transport
!    model GEOS-Chem, Atmos. Env., doi:10.1016/j.atmosenv.2014.02.001, 2014.
!  Fisher et al, Organic nitrate chemistry and its implications for nitrogen
!    budgets in an isoprene- and monoterpene-rich atmosphere: constraints from
!    aircraft (SEAC4RS) and ground-based (SOAS) observations in the Southeast
!    US. Atmos. Chem. Phys., 16, 2961-2990, 2016.
!  Marais et al., Aqueous-phase mechanism for secondary organic aerosol
!    formation from isoprene: application to the southeast United States and
!    co-benefit of SO2 emission controls, Atmos. Chem. Phys., 16, 1603-1618,
!    doi:10.5194/acp-16-1603-2016, 2016.
!  Parrella et al, Tropospheric bromine chemistry: implications for present and
!    pre-industrial ozone and mercury, Atmos. Chem. Phys., 12, 6,723-6,740,
!    doi:10.5194/acp-12-6723-2012, 2012.
!  Sherwen, T., et al., Global impacts of tropospheric halogens (Cl, Br, I) on
!    oxidants and composition in GEOS-Chem, Atmos. Chem. Phys., 16, 12239-12271,
!    https://doi.org/10.5194/acp-16-12239-2016, 2016.
!
! !REVISION HISTORY:
!  14 Dec 2015 - M. Long     - Initial version
!  29 Jan 2016 - M. Sulprizio- Update to include heterogeneous chemistry for
!                              UCX mechanism
!  29 Mar 2016 - R. Yantosca - NOTE: SPC_HBR and SPC_HOBR are defined
!                              for trop-only mechanisms
!  29 Mar 2016 - R. Yantosca - Added ProTeX headers
!  29 Mar 2016 - R. Yantosca - Moved all the UCX-based functions to the
!                              end of the module, for clarity
!  01 Apr 2016 - R. Yantosca - Remove many global variables that can be
!                              declared locally from the THREADPRIVATEs
!  06 Jun 2016 - M. Sulprizio- Replace Get_Indx with Spc_GetIndx to use the
!                              fast-species lookup from the species database
!  14 Jun 2016 - M. Sulprizio- Replace Spc_GetIndx with Ind_
!  15 Jun 2017 - M. Sulprizio- Add heterogeneous chemistry for isoprene SOA from
!                              E. Marais (Marais et al., 2016)
!  14 Jul 2017 - M. Sulprizio- Add heterogeneous chemistry for monoterpenes from
!                              J. Fisher (Fisher et al., 2017)
!  24 Aug 2017 - M. Sulprizio- Remove support for GCAP, GEOS-4, GEOS-5 and MERRA
!  15 Nov 2017 - M. Sulprizio- Add modifications for HOBr + S(IV) based on work
!                              by Qianjie Chen
!  24 Jan 2018 - X. Wang     - Updated chemistry for particle Cl- and Br-
!EOP
!------------------------------------------------------------------------------
!BOC
  CONTAINS
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: Set_Het
!
! !DESCRIPTION: Main heterogenous chemistry driver routine.  Sets up the
!  vector of heterogeneous chemistry rates for the KPP chemistry solver.
!\\
!\\
! !INTERFACE:
!
    SUBROUTINE SET_HET( I, J, L, SD, SC, SM, IO, SCF )
!
! !INPUT PARAMETERS: 
!
      INTEGER        :: I, J, L   ! Lon, lat, level indices
      TYPE(MetState) :: SM        ! Meteorology State object
      TYPE(OptInput) :: IO        ! Input Options object 

!
! !INPUT/OUTPUT PARAMETERS: 
!
      TYPE(ChmState) :: SC        ! Chemistry State object
      TYPE(DgnState) :: SD        ! Diagnostics State object
      REAL(fp)       :: SCF(3)    ! Coefficients (Need help documenting this)
!
! !REMARKS:
!
! !REVISION HISTORY:
!  06 Jan 2015 - R. Yantosca - Initial version
!  01 Apr 2016 - R. Yantosca - Define many variables locally that don't
!                              need to be in the THREADPRIVATE statements 
!  01 Apr 2016 - R. Yantosca - Remove KII_KI; we now declare that locally
!  31 May 2016 - E. Lundgren - Replace IO%XNUMOL with emMW_g from species
!                              database (emitted species g/mol)
!  26 Jul 2017 - M. Sulprizio- Remove hardcoded molecular weights from calls to
!                              Het* functions and use MW from species database
!                              instead
!  31 Jan 2018 - X. Wang     - Correct the calculations of halide concentrations
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      ! Scalars
      LOGICAL  :: SAFEDIV
      INTEGER  :: IND
      REAL(fp) :: ADJUSTEDRATE, CONSEXP,  DUMMY,    HBr_RTEMP
      REAL(fp) :: HOBr_RTEMP,   QICE,     QLIQ,     SPC_BrNO3
      REAL(fp) :: SPC_ClNO3,    SPC_H2O,  SPC_HBr,  SPC_HCl
      REAL(fp) :: SPC_HOBr,     SPC_HOCl, SPC_N2O5, VPRESH2O
      LOGICAL, SAVE :: FIRST = .TRUE.

      ! New treatment for educt removal
      Real(fp),Pointer :: spcVec(:)
      Real(fp)         :: kITemp, kIITemp

      ! Cloud parameters
      Real(fp)         :: rLiq, ALiq, VLiq
      Real(fp)         :: rIce, AIce, VIce
      Real(fp)         :: CF

      ! Volume of air (cm3)
      Real(fp)         :: VAir

      ! New bromine/chlorine chemistry
      Logical, Parameter :: fixedSaltBr=.True.
      Logical            :: useSaltBr
      Real(fp)           :: hConc_Sul
      Real(fp)           :: hConc_LCl
      Real(fp)           :: hConc_ICl
      Real(fp)           :: hConc_SSA
      Real(fp)           :: hConc_SSC
      Real(fp)           :: brConc_Base
      Real(fp)           :: brConc_SALA, clConc_SALA
      Real(fp)           :: brConc_SALC, clConc_SALC
      Real(fp)           :: brConc_CldA, clConc_CldA
      Real(fp)           :: brConc_CldC, clConc_CldC
      Real(fp)           :: brConc_Cldg, clConc_Cldg
      Real(fp)           :: brConc_Cld, clConc_Cld
      !Real(fp)           :: brConc_SALAg, brConc_SALAa, brConc_SALAr
      Real(fp)           :: pHCloud, pHSSA(2)
      Real(fp)           :: SSAlk(2)

      ! Debug
      Integer, Parameter :: IMax=50
      Integer, Parameter :: JMax=8
      Integer, Parameter :: LMax=40

      INTEGER :: N

      !====================================================================
      ! SET_HET begins here!
      !====================================================================

      ! Zero scalars and arrays
      ADJUSTEDRATE  = 0.0_fp
      CONSEXP       = 0.0_fp
      DUMMY         = 0.0_fp
      HBr_RTEMP     = 0.0_fp
      HOBr_RTEMP    = 0.0_fp
      KHETI_SLA     = 0.0_fp
      NAERO         = SC%nAero
      QICE          = 0.0_fp
      QLIQ          = 0.0_fp
      SPC_BrNO3     = 0.0_fp
      SPC_ClNO3     = 0.0_fp
      SPC_H2O       = 0.0_fp
      SPC_HBr       = 0.0_fp
      SPC_HCl       = 0.0_fp
      SPC_HOBr      = 0.0_fp
      SPC_HOCl      = 0.0_fp
      SPC_N2O5      = 0.0_fp
      VPRESH2O      = 0.0_fp

      ! Initialize logicals
      SAFEDIV       = .FALSE.
      PSCBOX        = .FALSE.
      STRATBOX      = .FALSE.
      NATSURFACE    = .FALSE.

      ! KHETI_SLA = sticking coefficients for PSC reactions on SLA
      IF ( IO%LUCX ) THEN
         KHETI_SLA  = SC%KHETI_SLA(I,J,L,:)
      ENDIF

      ! Point to the chemical species array [molec/cm3]
      spcVec          => SC%Species(I,J,L,:)

      !--------------------------------------------------------------------
      ! Calculate RH [%]
      ! Not clear why this calc is slightly different than SM%RH
      !--------------------------------------------------------------------
      RELHUM        = SM%AVGW(I,J,L) * SM%AIRNUMDEN(I,J,L)
      CONSEXP       = 17.2693882e+0_fp * (SM%T(I,J,L) - 273.16e+0_fp) / &
                      (SM%T(I,J,L) - 35.86e+0_fp)
      VPRESH2O      = CONSVAP * EXP(CONSEXP) / SM%T(I,J,L) 
      RELHUM        = RELHUM / VPRESH2O 
      RELHUM        = RELHUM * 100e+0_fp

      !--------------------------------------------------------------------
      ! Get species molecular weights [kg/mol]
      !--------------------------------------------------------------------
      IF ( FIRST) THEN
         ! Hardcode HO2 for now
         ! MW_g is not defined for HO2 in the species database but model
         ! output changes when it is added there (mps, 7/26/17)
         MW_HO2    = 33.0_fp

         IND = Ind_( 'NO2' )
         IF ( IND > 0 ) MW_NO2    = SC%SpcData(IND)%Info%MW_g

         IND = Ind_( 'NO3' )
         IF ( IND > 0 ) MW_NO3    = SC%SpcData(IND)%Info%MW_g

         IND = Ind_( 'N2O5' )
         IF ( IND > 0 ) MW_N2O5   = SC%SpcData(IND)%Info%MW_g

         IND = Ind_( 'GLYX' )
         IF ( IND > 0 ) MW_GLYX   = SC%SpcData(IND)%Info%MW_g

         IND = Ind_( 'MGLY' )
         IF ( IND > 0 ) MW_MGLY   = SC%SpcData(IND)%Info%MW_g

         IND = Ind_( 'IEPOXA' )
         IF ( IND > 0 ) MW_IEPOXA = SC%SpcData(IND)%Info%MW_g

         IND = Ind_( 'IEPOXB' )
         IF ( IND > 0 ) MW_IEPOXB = SC%SpcData(IND)%Info%MW_g

         IND = Ind_( 'IEPOXD' )
         IF ( IND > 0 ) MW_IEPOXD = SC%SpcData(IND)%Info%MW_g

         IND = Ind_( 'IMAE' )
         IF ( IND > 0 ) MW_IMAE   = SC%SpcData(IND)%Info%MW_g

         IND = Ind_( 'LVOC' )
         IF ( IND > 0 ) MW_LVOC   = SC%SpcData(IND)%Info%MW_g

         IND = Ind_( 'ISN1OG' )
         IF ( IND > 0 ) MW_ISN1OG = SC%SpcData(IND)%Info%MW_g

         IND = Ind_( 'ISOPND' )
         IF ( IND > 0 ) MW_ISOPND = SC%SpcData(IND)%Info%MW_g

         IND = Ind_( 'ISOPNB' )
         IF ( IND > 0 ) MW_ISOPNB = SC%SpcData(IND)%Info%MW_g

         IND = Ind_( 'MACRN' )
         IF ( IND > 0 ) MW_MACRN  = SC%SpcData(IND)%Info%MW_g

         IND = Ind_( 'MVKN' )
         IF ( IND > 0 ) MW_MVKN   = SC%SpcData(IND)%Info%MW_g

         IND = Ind_( 'R4N2' )
         IF ( IND > 0 ) MW_R4N2   = SC%SpcData(IND)%Info%MW_g

         IND = Ind_( 'DHDN' )
         IF ( IND > 0 ) MW_DHDN   = SC%SpcData(IND)%Info%MW_g

         IND = Ind_( 'MONITS' )
         IF ( IND > 0 ) MW_MONITS = SC%SpcData(IND)%Info%MW_g

         IND = Ind_( 'MONITU' )
         IF ( IND > 0 ) MW_MONITU = SC%SpcData(IND)%Info%MW_g

         IND = Ind_( 'HONIT' )
         IF ( IND > 0 ) MW_HONIT  = SC%SpcData(IND)%Info%MW_g

         IND = Ind_( 'IONITA' )
         IF ( IND > 0 ) MW_IONITA = SC%SpcData(IND)%Info%MW_g

         IND = Ind_( 'MONITA' )
         IF ( IND > 0 ) MW_MONITA = SC%SpcData(IND)%Info%MW_g

         IND = Ind_( 'BrNO3' )
         IF ( IND > 0 ) MW_BrNO3  = SC%SpcData(IND)%Info%MW_g

         IND = Ind_( 'HOBr' )
         IF ( IND > 0 ) MW_HOBr   = SC%SpcData(IND)%Info%MW_g

         IND = Ind_( 'HBr' )
         IF ( IND > 0 ) MW_HBr    = SC%SpcData(IND)%Info%MW_g

         IND = Ind_( 'ClNO3' )
         IF ( IND > 0 ) MW_ClNO3  = SC%SpcData(IND)%Info%MW_g

         IND = Ind_( 'HOCl' )
         IF ( IND > 0 ) MW_HOCl   = SC%SpcData(IND)%Info%MW_g

         IND = Ind_( 'HI' )
         IF ( IND > 0 ) MW_HI     = SC%SpcData(IND)%Info%MW_g

         IND = Ind_( 'HOI' )
         IF ( IND > 0 ) MW_HOI    = SC%SpcData(IND)%Info%MW_g

         IND = Ind_( 'I2O2' )
         IF ( IND > 0 ) MW_I2O2   = SC%SpcData(IND)%Info%MW_g

         IND = Ind_( 'I2O3' )
         IF ( IND > 0 ) MW_I2O3   = SC%SpcData(IND)%Info%MW_g

         IND = Ind_( 'I2O4' )
         IF ( IND > 0 ) MW_I2O4   = SC%SpcData(IND)%Info%MW_g

         IND = Ind_( 'IONO' )
         IF ( IND > 0 ) MW_IONO   = SC%SpcData(IND)%Info%MW_g

         IND = Ind_( 'IONO2' )
         IF ( IND > 0 ) MW_IONO2  = SC%SpcData(IND)%Info%MW_g

         ! Reset flag
         FIRST = .FALSE.

      ENDIF

      !--------------------------------------------------------------------
      ! Get species concentrations [molec/cm3]
      !--------------------------------------------------------------------
      IND = Ind_( 'NIT' )
      IF (IND .le. 0) THEN
         SPC_NIT    = 0.0e+0_fp
      ELSE
         SPC_NIT    = spcVec(IND)
      ENDIF

      IND = Ind_( 'NITS' )
      IF (IND .le. 0) THEN
         SPC_NITs   = 0.0e+0_fp
      ELSE
         SPC_NITs   = spcVec(IND)
      ENDIF

      IND = Ind_('SO4')
      IF (IND .le. 0) THEN
         SPC_SO4    = 0.0e+0_fp
      ELSE
         SPC_SO4    = spcVec(IND)
      ENDIF

      IND = Ind_('SALACL')
      IF (IND .le. 0) THEN
         SPC_fCl    = 0.0e+0_fp
      ELSE
         SPC_fCl    = spcVec(IND)
      ENDIF

      IND = Ind_('SALCCL')
      IF (IND .le. 0) THEN
         SPC_cCl    = 0.0e+0_fp
      ELSE
         SPC_cCl    = spcVec(IND)
      ENDIF

      IND = Ind_('HBr')
      IF (IND .le. 0) THEN
         SPC_HBr    = 0.0e+0_fp
      ELSE
         SPC_HBr    = spcVec(IND)
      ENDIF

      IND = Ind_('HOBr')
      IF (IND .le. 0) THEN
         SPC_HOBr   = 0.0e+0_fp
      ELSE
         SPC_HOBr   = spcVec(IND)
      ENDIF

      !--------------------------------------------------------------------
      ! Get fields required for epoxide uptake hydrolysis (EPOXUPTK)
      ! These values are saved in isorropiaII_mod.F
      !--------------------------------------------------------------------
      ! Proton activity [unitless] and H+ concentration [M]
      ! (assumed equivalent - for now):
      H_PLUS = SC%HplusSav(I,J,L,1)

      ! Sulfate concentration [M]:
      MSO4   = SC%SulRatSav(I,J,L)

      ! Nitrate concentration [M]:
      MNO3   = SC%NaRatSav(I,J,L,1)

      ! Bisulfate (general acid) concentration [M]:
      MHSO4  = SC%BisulSav(I,J,L)

      !--------------------------------------------------------------------
      ! Get fields from State_Met, State_Chm, and Input_Opt
      !--------------------------------------------------------------------
      XAREA(1:SC%nAero) = SC%AeroArea(I,J,L,:) ! Aerosol area [cm2/cm3]
      XRADI(1:SC%nAero) = SC%AeroRadi(I,J,L,:) ! Aerosol radius [cm]
      AClAREA = SC%AClArea(I,J,L)      !Fine Cl- aerosol area [cm2/cm3]
      AClRADI = SC%AClRadi(I,J,L)    !Fine Cl- aerosol radius [cm]
      AWATER(:) = SC%WaterSav(I,J,L,:) 

      TEMPK  = SM%T(I,J,L)                     ! Temperature [K]
      XTEMP  = sqrt(SM%T(I,J,L))               ! Square root of temperature
      XDENA  = SM%AIRNUMDEN(I,J,L)             ! Dry air density [molec/cm3]
      SUNCOS = SM%SUNCOSmid(I,J)               ! COS(SZA),midpt of chem timestep
      VAir   = SM%AIRVOL(I,J,L)*1.0e6_fp       ! Volume of air (cm3)
      QICE   = SM%QI(I,J,L)                    ! Ice   mix ratio [kg/kg dry air]
      QLIQ   = SM%QL(I,J,L)                    ! Water mix ratio [kg/kg dry air]
      CF     = SM%CLDF(I,J,L)                  ! Cloud fraction
      CF     = max(CF, 0.0e0_fp)
      CF     = min(CF, 1.0e0_fp)

      GAMMA_HO2 = IO%GAMMA_HO2

#if defined( UCX )
      !--------------------------------------------------------------------
      ! Check surface type of PSCs (SDE 04/17/13)
      !--------------------------------------------------------------------
      CALL CHECK_NAT( I,  J,  L, NATSURFACE, PSCBOX, STRATBOX, &
                      IO, SM, SC )
#endif

      !--------------------------------------------------------------------
      !  Calculate parameters for cloud halogen chemistry
      !  under the new scheme (SDE 2016-12-21)
      !--------------------------------------------------------------------

      ! Get cloud physical parameters
      CALL Cld_Params( I, J, L, XDenA, VAir, TempK, QLiq, QIce, SM, &
                       rLiq,  ALiq,  VLiq, rIce,  AIce,  VIce )

      ! Retrieve cloud pH and alkalinity
      pHCloud = SC%pHCloud(I,J,L)
      pHSSA(:) = SC%pHSav(I,J,L,:)
      ! Since we have Alk tracers, SC%SSAlk may be removed in future
      ! Here still use SC%SSAlk instead of Alk tracers, 
      ! to skip unit conversion. xnw 1/24/18
      SSAlk(1:2) = SC%SSAlk(I,J,L,1:2)

      ! Estimate liquid phase pH (H+ concentration)
      !hConc_Sul = 10.0**(-0.0e+0_fp)       
      hConc_Sul = 10.0**(-1.0e+0_fp*pHSSA(1))
      hConc_LCl = 10.0**(-1.0e+0_fp*pHCloud)
      hConc_ICl = 10.0**(-4.5e+0_fp) 
      !hConc_SSA = 10.0**(-5.0e+0_fp) 
      hConc_SSA = hConc_Sul
      hConc_SSC = 10.0**(-5.0e+0_fp)

      ! If not using BrSALA, manually set a depleted Br- concentration (mol/l)
      useSaltBr = ((.not.fixedSaltBr).and.(Ind_('BrSALA') > 0))
      IF (useSaltBr) THEN
         brConc_Base = 0.0e+0_fp
      ELSE
         brConc_Base = 1.0e+4_fp
      ENDIF 

      ! Because there is no thermodynamics for HBr/Br-, the Br- concentrations in
      ! cloud and fine mode aerosols are similar as previous


      ! Get halide concentrations, in cloud      

      !IF (SSAlk(1)<=0.05e0_fp) THEN
         !CALL Get_Halide_CldConc(spcVec(Ind_('BrSALA')*0.7), VLiq, VIce, VAir, TempK, &
         !                  CF, brConc_CldA)
         brConc_CldA = 0.0e0_fp
         CALL Get_Halide_CldConc(spcVec(Ind_('SALACL')*0.7), VLiq, VIce, VAir, TempK, &
                           CF, clConc_CldA)
         CALL Get_Halide_CldConc_g(spcVec(Ind_('HBr')), spcVec(Ind_('HCl')), VLiq, &
                           VIce, VAir, TempK, CF, brConc_Cldg, clConc_Cldg)
      !ELSE
      !   brConc_CldA = 1.0e-20_fp
      !   clConc_CldA = 1.0e-20_fp
      !   CALL Get_Halide_CldConc_g(spcVec(Ind_('HBr')), spcVec(Ind_('HCl')), VLiq, &
      !                     VIce, VAir, TempK, CF, brConc_Cldg, clConc_Cldg)
      !ENDIF

      !clConc_Cldg =  1.0e-20_fp      
      !brConc_Cldg =  1.0e-20_fp

      IF (SSAlk(2)<=0.05e0_fp) THEN
         !CALL Get_Halide_CldConc(spcVec(Ind_('BrSALC')*0.9), VLiq, VIce, VAir, TempK, &
         !                  CF, brConc_CldC)
         brConc_CldC = 0.0e0_fp
         CALL Get_Halide_CldConc(spcVec(Ind_('SALCCL')*0.9), VLiq, VIce, VAir, TempK, &
                           CF, clConc_CldC)
      ELSE
         brConc_CldC = 1.0e-20_fp
         clConc_CldC = 1.0e-20_fp
      ENDIF

      brConc_Cld = brConc_CldA + brConc_CldC + brConc_Cldg
      clConc_Cld = clConc_CldA + clConc_CldC + clConc_Cldg

      ! Get halide concentrations, in aerosol
      ! Note that here Br/ClSALA = Br/Cl- in (SALA + sulfate)
      ! Get the concentration of Br-
      CALL Get_Halide_SSAConc(spcVec(Ind_('BrSALA')), AClAREA,AClRADI, brConc_SALA)
      CALL Get_Halide_SSAConc(spcVec(Ind_('BrSALC')), xArea(12),xRadi(12), brConc_SALC)
      ! Get the concentration of Cl-
      CALL Get_Halide_SSAConc(spcVec(Ind_('SALACL')), AClAREA,AClRADI, clConc_SALA)
      CALL Get_Halide_SSAConc(spcVec(Ind_('SALCCL')), xArea(12),xRadi(12), clConc_SALC)
      ! Get the concentration of NO3-
      CALL Get_Halide_SSAConc(spcVec(Ind_('NIT')), AClAREA,AClRADI,nitConc_SALA)
      CALL Get_Halide_SSAConc(spcVec(Ind_('NITs')), xArea(12),xRadi(12),nitConc_SALC)      

      !--------------------------------------------------------------------
      !  Get parameters for HOBr + S(IV)
      !--------------------------------------------------------------------

      ! Cloud bisulfite (HSO3-) concentration [mol/l] from sulfate_mod.F
      HSO3conc_Cld = SC%HSO3_AQ(I,J,L)

      ! Cloud sulfite (SO3--) concentration [mol/l] from sulfate_mod.F
      SO3conc_Cld  = SC%SO3_AQ(I,J,L)

      ! Avoid div-by-zero issues in GAMMA_HOBr_X
      !IF ( HSO3conc_Cld <= 0.0_fp) HSO3conc_Cld = 1e-20_fp
      !IF (  SO3conc_Cld  <= 0.0_fp)  SO3conc_Cld = 1e-20_fp

      ! Correction factor for HOBr removal by SO2 [unitless]
      fupdateHOBr  = SC%fupdateHOBr(I,J,L)

      !--------------------------------------------------------------------
      ! Calculate and pass het rates to the KPP rate array
      !--------------------------------------------------------------------

      ! Zero the HET array
      HET = 0.0_dp

      ! Calculate genuine first-order uptake reactions first
      HET(ind_HO2,    1) = HetHO2(        MW_HO2,    2E-1_fp)
      HET(ind_NO2,    1) = HetNO2(        MW_NO2,    1E-4_fp)
      HET(ind_NO3,    1) = HetNO3(        MW_NO3,    1E-1_fp)
      HET(ind_GLYX,   1) = HetGLYX(       MW_GLYX,   1E-1_fp)
      HET(ind_MGLY,   1) = HetMGLY(       MW_MGLY,   1E-1_fp)
      HET(ind_IEPOXA, 1) = HetIEPOX(      MW_IEPOXA, 1E-1_fp)
      HET(ind_IEPOXB, 1) = HetIEPOX(      MW_IEPOXB, 1E-1_fp)
      HET(ind_IEPOXD, 1) = HetIEPOX(      MW_IEPOXD, 1E-1_fp)
      HET(ind_IMAE,   1) = HetIMAE(       MW_IMAE,   1E-1_fp)
      HET(ind_LVOC,   1) = HetLVOC(       MW_LVOC,   1E+0_fp)
      HET(ind_ISN1OG, 1) = HetISN1OG(     MW_ISN1OG, 1E+0_fp)
      HET(ind_ISOPND, 1) = HetISOPND(     MW_ISOPND, 5E-3_fp)
      HET(ind_ISOPNB, 1) = HetISOPNB(     MW_ISOPNB, 5E-3_fp)
      HET(ind_MACRN,  1) = HetMACRN(      MW_MACRN,  5E-3_fp)
      HET(ind_MVKN,   1) = HetMVKN(       MW_MVKN,   5E-3_fp)
      HET(ind_R4N2,   1) = HetR4N2(       MW_R4N2,   5E-3_fp)
      HET(ind_DHDN,   1) = HetDHDN(       MW_DHDN,   5E-3_fp)
      HET(ind_MONITS, 1) = HetMONITS(     MW_MONITS, 1E-2_fp)
      HET(ind_MONITU, 1) = HetMONITU(     MW_MONITU, 1E-2_fp)
      HET(ind_HONIT,  1) = HetHONIT(      MW_HONIT,  1E-2_fp)
      HET(ind_IONITA, 1) = HetIONITA(     MW_IONITA, 1E-1_fp)
      HET(ind_MONITA, 1) = HetMONITA(     MW_MONITA, 1E-1_fp)

      ! Now calculate reaction rates where the educt can be consumed.
      ! kIIR1Ltd: Assume that the first reactant is limiting. Assume that the
      ! second reactant is "abundant" and calculate the overall rate based on
      ! the uptake rate of the first reactant only.
      HET(ind_N2O5,  1) = HETN2O5(1.08E2_fp, 1E-1_fp, clConc_SALA, clConc_SALC)

      !--------------------------------------------------------------------
      ! Br/Cl heterogeneous chemistry
      !--------------------------------------------------------------------
      IF (Ind_('ClNO3') > 0) THEN

         !----------------------------------------------------------------
         ! Cl- enhanced NO3 hydrolysis (XW 2018-03-16)
         !----------------------------------------------------------------
         kITemp = HetNO3_Cl(XDenA, AClRADI, AClAREA, TempK, clConc_SALA)
         HET(ind_NO3, 2) = kITemp
         kITemp = HetNO3_Cl(XDenA, XRADI(12), XAREA(12), TempK, clConc_SALC)
         HET(ind_NO3, 3) = kITemp

         !----------------------------------------------------------------
         ! ClNO3 and BrNO3 hydrolysis (SDE 2016-12-21)
         !----------------------------------------------------------------
         kITemp = HETBrNO3_JS( XDenA, rLiq, rIce, ALiq, AIce, TempK)
         HET(ind_BrNO3, 1) = kIIR1Ltd( spcVec, Ind_('BrNO3'), Ind_('H2O'), &
                                       kITemp, HetMinLife)
         kITemp = HETClNO3_JS( XDenA, rLiq, rIce, ALiq, AIce, TempK, clConc_SALA, brConc_SALA, clConc_Cld, brConc_Cld, CF)
         HET(ind_ClNO3, 1) = kIIR1Ltd( spcVec, Ind_('ClNO3'), Ind_('H2O'), &
                                       kITemp, HetMinLife)

         !----------------------------------------------------------------
         ! HOBr + HBr (TS index: hhc06)
         !----------------------------------------------------------------
         !kITemp = HETHOBr_HBr_JS(MW_HOBr, 0e+0_fp)
         kITemp = HETHOBr_TCld( XDenA, rLiq, rIce, ALiq, AIce, VAir, TempK, &
                           hConc_Sul, hConc_LCl, hConc_ICl, clConc_CldA, clConc_CldC, clConc_Cldg, &
                           brConc_CldA, brConc_CldC, brConc_Cldg, HSO3conc_Cld, SO3conc_Cld, 6)
         !kITemp = kITemp + &
         !         HETHOBr_SS_JS( XDenA, AClRADI, (1-CF)*AClAREA, SSAlk(1), TempK, &
         !                        hConc_SSA, clConc_SALA, brConc_SALA, 2, brConc_SALAr )  
         HET(ind_HOBr,  1) = kIIR1Ltd( spcVec, Ind_('HOBr'),  Ind_('HBr'), &
                                       kITemp, HetMinLife)

         !----------------------------------------------------------------
         ! HOBr + HCl (TS index: hhc03)
         !----------------------------------------------------------------
         !kITemp = HETHOBr_HCl_JS(MW_HOBr, 0e+0_fp)
         kITemp = HETHOBr_TCld( XDenA, rLiq, rIce, ALiq, AIce, VAir, TempK, &
                           hConc_Sul, hConc_LCl, hConc_ICl, clConc_CldA, clConc_CldC, clConc_Cldg, &
                           brConc_CldA, brConc_CldC, brConc_Cldg, HSO3conc_Cld, SO3conc_Cld, 5)
         HET(ind_HOBr,  2) = kIIR1Ltd( spcVec, Ind_('HOBr'),  Ind_('HCl'), &
                                       kITemp, HetMinLife)

         !----------------------------------------------------------------
         ! HOBr + BrSalA/C (TS index: hhc07/08)
         !----------------------------------------------------------------
         ! First consider reaction in troposphere cloud
         kITemp = HETHOBr_TCld( XDenA, rLiq, rIce, ALiq, AIce, VAir, TempK, &
                           hConc_Sul, hConc_LCl, hConc_ICl, clConc_CldA, clConc_CldC, clConc_Cldg, &
                           brConc_CldA, brConc_CldC, brConc_Cldg, HSO3conc_Cld, SO3conc_Cld, 3)
         ! Then calculate reaction on aerosols out of cloud
         kITemp = kITemp + &
                  HETHOBr_SS_JS( XDenA, AClRADI, (1.0-CF)*AClAREA, SSAlk(1), TempK, &
                                 hConc_SSA, clConc_SALA, brConc_SALA, 2)
         HET(ind_HOBr,  5) = kIIR1Ltd( spcVec, Ind_('HOBr'),  Ind_('BrSALA'), &
                                       kITemp, HetMinLife)
         
         ! First consider reaction in troposphere cloud
         kITemp = HETHOBr_TCld( XDenA, rLiq, rIce, ALiq, AIce, VAir, TempK, &
                           hConc_Sul, hConc_LCl, hConc_ICl, clConc_CldA, clConc_CldC, clConc_Cldg, &
                           brConc_CldA, brConc_CldC, brConc_Cldg, HSO3conc_Cld, SO3conc_Cld, 4)
         ! Then calculate reaction on aerosols out of cloud
         kITemp = kITemp + &
                  HETHOBr_SS_JS( XDenA, xRadi(12), (1.0-CF)*xArea(12), SSAlk(2), TempK, &
                                 hConc_SSC, clConc_SALC, brConc_SALC, 2)
         HET(ind_HOBr,  6) = kIIR1Ltd( spcVec, Ind_('HOBr'),  Ind_('BrSALC'), &
                                       kITemp, HetMinLife)

         !----------------------------------------------------------------
         ! HOBr + Cl-(p) (TS index: hhc04/05)
         !----------------------------------------------------------------
         ! Updated to include Cl-(p), xnw 1/24/18
         ! First consider reaction in troposphere cloud
         kITemp = HETHOBr_TCld( XDenA, rLiq, rIce, ALiq, AIce, VAir, TempK, &
                           hConc_Sul, hConc_LCl, hConc_ICl, clConc_CldA, clConc_CldC, clConc_Cldg, &
                           brConc_CldA, brConc_CldC, brConc_Cldg, HSO3conc_Cld, SO3conc_Cld, 1)
         ! Then calculate reaction on aerosols out of cloud
         kITemp = kITemp + &
                  HETHOBr_SS_JS( XDenA, AClRADI, (1.0-CF)*AClAREA, SSAlk(1), TempK, &
                                 hConc_SSA, clConc_SALA, brConc_SALA, 1)
         HET(ind_HOBr,  3) = kIIR1Ltd( spcVec, Ind_('HOBr'),  Ind_('SALACL'), &
                                       kITemp, HetMinLife)

         kITemp = HETHOBr_TCld( XDenA, rLiq, rIce, ALiq, AIce, VAir, TempK, &
                           hConc_Sul, hConc_LCl, hConc_ICl, clConc_CldA, clConc_CldC, clConc_Cldg, &
                           brConc_CldA, brConc_CldC, brConc_Cldg, HSO3conc_Cld, SO3conc_Cld, 2)
         ! Then calculate reaction on aerosols out of cloud
         kITemp = kITemp + &
                  HETHOBr_SS_JS( XDenA, xRadi(12), (1.0-CF)*xArea(12), SSAlk(2), &
                                 TempK, hConc_SSC, clConc_SALC, brConc_SALC, 1)
         HET(ind_HOBr,  4) = kIIR1Ltd( spcVec, Ind_('HOBr'),  Ind_('SALCCL'), &
                                       kITemp, HetMinLife)

         !----------------------------------------------------------------
         ! HOBr + HSO3-(aq) (QJC index: EhcHSHOBCld)
         !----------------------------------------------------------------
         ! This reaction is first order, so no kII calculation is required
         kITemp = HETHOBr_HSO3( XDenA, rLiq, rIce, ALiq, AIce, VAir, TempK, &
                             hConc_Sul, hConc_LCl, hConc_ICl, clConc_Cld, &
                             brConc_Cld, HSO3conc_Cld, SO3conc_Cld )

         ! Make sure sulfate produced is less than SO2 available (qjc, 06/20/16)
         HET(ind_HOBr,  7) = kITemp * fupdateHOBr

         !----------------------------------------------------------------
         ! HOBr + SO3--(aq) (QJC index: EhcSOHOBCld)
         !----------------------------------------------------------------
         ! This reaction is first order, so no kII calculation is required
         kITemp = HETHOBr_SO3( XDenA, rLiq, rIce, ALiq, AIce, VAir, TempK, &
                             hConc_Sul, hConc_LCl, hConc_ICl, clConc_Cld, &
                             brConc_Cld, HSO3conc_Cld, SO3conc_Cld )

         ! Make sure sulfate produced is less than SO2 available (qjc, 06/20/16)
         HET(ind_HOBr,  8) = kITemp * fupdateHOBr

         !----------------------------------------------------------------
         ! ClNO3 + BrSALA/C (TS index: hhc10/11)
         !----------------------------------------------------------------
         ! First consider reaction in troposphere cloud
         kITemp = HETClNO3_TCld( XDenA, rLiq, rIce, ALiq, AIce, VAir, TempK, &
                           clConc_CldA, clConc_CldC, clConc_Cldg, brConc_CldA, brConc_CldC, brConc_Cldg, 3)
         ! Then calculate reaction on aerosols out of cloud
         kITemp = kITemp + &
                  HETClNO3_SS_JS( XDenA, AClRADI, (1.0-CF)*AClAREA, SSAlk(1), &
                                  TempK, clConc_SALA, brConc_SALA, 2, 1)
         HET(ind_ClNO3, 4) = kIIR1Ltd( spcVec, Ind_('ClNO3'), Ind_('BrSALA'), &
                                       kITemp, HetMinLife)

         ! First consider reaction in troposphere cloud
         kITemp = HETClNO3_TCld( XDenA, rLiq, rIce, ALiq, AIce, VAir, TempK, &
                           clConc_CldA, clConc_CldC, clConc_Cldg, brConc_CldA, brConc_CldC, brConc_Cldg, 4)
         ! Then calculate reaction on aerosols out of cloud
         kITemp = kITemp + &
                  HETClNO3_SS_JS( XDenA, xRadi(12), (1.0-CF)*xArea(12), SSAlk(2), &
                                  TempK, clConc_SALC, brConc_SALC, 2, 2)
         HET(ind_ClNO3, 5) = kIIR1Ltd( spcVec, Ind_('ClNO3'), Ind_('BrSALC'), &
                                       kITemp, HetMinLife)

         !----------------------------------------------------------------
         ! ClNO3 + Cl-(p) (XW, 1/24/18)
         !----------------------------------------------------------------
         ! First consider reaction in troposphere cloud
         kITemp = HETClNO3_TCld( XDenA, rLiq, rIce, ALiq, AIce, VAir, TempK, &
                           clConc_CldA, clConc_CldC, clConc_Cldg, brConc_CldA, brConc_CldC, brConc_Cldg, 1)
         ! Then calculate reaction on aerosols out of cloud
         kITemp = kITemp + &
                  HETClNO3_SS_JS( XDenA, AClRADI, (1.0-CF)*AClAREA, SSAlk(1), &
                                  TempK, clConc_SALA, brConc_SALA, 1, 1)
         HET(ind_ClNO3, 6) = kIIR1Ltd( spcVec, Ind_('ClNO3'), Ind_('SALACL'), &
                                       kITemp, HetMinLife)

         ! First consider reaction in troposphere cloud
         kITemp = HETClNO3_TCld( XDenA, rLiq, rIce, ALiq, AIce, VAir, TempK, &
                           clConc_CldA, clConc_CldC, clConc_Cldg, brConc_CldA, brConc_CldC, brConc_Cldg, 2)
         ! Then calculate reaction on aerosols out of cloud
         kITemp = kITemp + &
                  HETClNO3_SS_JS( XDenA, xRadi(12), (1.0-CF)*xArea(12), SSAlk(2), &
                                  TempK, clConc_SALC, brConc_SALC, 1, 2)
         HET(ind_ClNO3, 7) = kIIR1Ltd( spcVec, Ind_('ClNO3'), Ind_('SALCCL'), &
                                       kITemp, HetMinLife)

         !----------------------------------------------------------------
         ! ClNO3 + HCl 
         !----------------------------------------------------------------
         !kITemp = HETClNO3_HCl( MW_ClNO3, 0e+0_fp )
         kITemp = HETClNO3_TCld( XDenA, rLiq, rIce, ALiq, AIce, VAir, TempK, &
                           clConc_CldA, clConc_CldC, clConc_Cldg, brConc_CldA, brConc_CldC, brConc_Cldg, 5)
         HET(ind_ClNO3, 2) = kIIR1Ltd( spcVec, Ind_('ClNO3'), Ind_('HCl'), &
                                       kITemp, HetMinLife)

         !----------------------------------------------------------------
         ! ClNO3 + HBr (TS index: hhc09)
         !----------------------------------------------------------------
         !kITemp = HETClNO3_HBr_JS( MW_ClNO3, 0e+0_fp )
         kITemp = HETClNO3_TCld( XDenA, rLiq, rIce, ALiq, AIce, VAir, TempK, &
                           clConc_CldA, clConc_CldC, clConc_Cldg, brConc_CldA, brConc_CldC, brConc_Cldg, 6)
         !kITemp = kITemp + &        
         !         HETClNO3_SS_JS( XDenA, AClRADI, (1.0-CF)*AClAREA, SSAlk(1), &
         !                         TempK, clConc_SALA, brConc_SALA, 2, 1, brConc_SALAr )
         HET(ind_ClNO3, 3) = kIIR1Ltd( spcVec, Ind_('ClNO3'), Ind_('HBr'), &
                                       kITemp, HetMinLife)

         !----------------------------------------------------------------
         ! HOCl + HCl and HOCl + HBr to take place in the troposphere
         !----------------------------------------------------------------
	 ! NOTE: the restriction of these reactions to the troposphere has been
         ! restored - tms (2017/04/06 )
         HET(ind_HOCl,  1) = kIIR1Ltd( spcVec, Ind_('HOCl'),  Ind_('HCl'), &
                             HETHOCl_HCl(  0.52E2_fp, 0E+0_fp), HetMinLife)
         HET(ind_HOCl,  2) = kIIR1Ltd( spcVec, Ind_('HOCl'),  Ind_('HBr'), &
                             HETHOCl_HBr(  0.52E2_fp, 0E+0_fp), HetMinLife)

         !----------------------------------------------------------------
         ! HOCl + Cl-(p) (XW, 1/24/18) 
         !----------------------------------------------------------------
         kITemp = HETHOCl_SS( XDenA, AClRADI, AClAREA, SSAlk(1), TempK, &
                             hConc_SSA, clConc_SALA)
         HET(ind_HOCl,  3) = kIIR1Ltd( spcVec, Ind_('HOCl'),  Ind_('SALACL'), &
                             kITemp, HetMinLife)
         kITemp = HETHOCl_SS( XDenA, xRadi(12), xArea(12), SSAlk(2), TempK, &
                             hConc_SSC, clConc_SALC)
         HET(ind_HOCl,  4) = kIIR1Ltd( spcVec, Ind_('HOCl'),  Ind_('SALCCL'), &
                             kITemp, HetMinLife)

         !----------------------------------------------------------------
         ! O3 + Br- calculation (TS index: hhc12)
         !----------------------------------------------------------------
         kITemp = HETO3_HBr_JS( XDenA, rLiq, rIce, ALiq, AIce, VAir, &
                                TempK, brConc_CldA, brConc_CldC, brConc_Cldg, spcVec(Ind_('O3')), 3)
         !kITemp = kITemp + &
         !         HETO3_SS_JS( XDenA, AClRADI, (1.0-CF)*AClAREA, SSAlk(1), &
         !                      TempK, brConc_SALA, spcVec(Ind_('O3')))
         HET(ind_O3,    1) = kIIR1Ltd( spcVec, Ind_('O3'), Ind_('HBr'), &
                                       kITemp, HetMinLife)

         !----------------------------------------------------------------
         ! O3 + BrSALA/C calculations (TS index: hhc13/14)
         !----------------------------------------------------------------
         kITemp = HETO3_HBr_JS( XDenA, rLiq, rIce, ALiq, AIce, VAir, &
                                TempK, brConc_CldA, brConc_CldC, brConc_Cldg, spcVec(Ind_('O3')), 1)
         kITemp = kITemp + HETO3_SS_JS( XDenA, AClRADI, (1.0-CF)*AClAREA, SSAlk(1), &
                               TempK, brConc_SALA, spcVec(Ind_('O3'))) 
         HET(ind_O3,    2) = kIIR1Ltd( spcVec, Ind_('O3'), Ind_('BrSALA'), &
                                       kITemp, HetMinLife)

         kITemp = HETO3_HBr_JS( XDenA, rLiq, rIce, ALiq, AIce, VAir, &
                                TempK, brConc_CldA, brConc_CldC, brConc_Cldg, spcVec(Ind_('O3')), 2)
         kITemp = kITemp + HETO3_SS_JS( XDenA, xRadi(12), (1.0-CF)*xArea(12), SSAlk(2), &
                               TempK, brConc_SALC, spcVec(Ind_('O3')))
         HET(ind_O3,    3) = kIIR1Ltd( spcVec, Ind_('O3'), Ind_('BrSALC'), &
                                       kITemp, HetMinLife)

         !----------------------------------------------------------------
         ! Br uptake calculation - forms BrSALA/C (TS index: hhc17/18)
         !----------------------------------------------------------------
         ! First-order reactions, no calculation of kII required
         kITemp = HETHXUptake_JS( XDenA, AClRADI, AClAREA, TempK, 2)
         HET(ind_HBr,   1) = kITemp
         kITemp = HETHXUptake_JS( XDenA, xRadi(12), xArea(12), TempK, 2)
         HET(ind_HBr,   2) = kITemp

         !----------------------------------------------------------------
         ! BrNO3 + HCl into the troposphere
         !----------------------------------------------------------------
         HET(ind_BrNO3, 2) = kIIR1Ltd( spcVec, Ind_('BrNO3'), Ind_('HCl'), &
                             HETBrNO3_HCl(  1.42E2_fp, 0E+0_fp), HetMinLife)

         !----------------------------------------------------------------
         ! N2O5 + HCl on sulfate
         !----------------------------------------------------------------
	 ! NOTE: this extension of calculation in troposphere has been removed
         !  (tms 17/04/10)
         kITemp = HETN2O5_HCl( 1.08E2_fp, 0.0e+0_fp ) 
         HET(ind_N2O5,  2) = kIIR1Ltd( spcVec, Ind_('N2O5'), Ind_('HCl'), &
                                       kITemp, HetMinLife) 

         !----------------------------------------------------------------
         ! Reaction of N2O5 with sea-salt Cl-
         ! Updated to include Cl-(p), XW 1/24/18)
         !----------------------------------------------------------------
         kITemp = HETN2O5_SS( XDenA, AClRADI, AClAREA, TempK, clConc_SALA, 1)
         HET(ind_N2O5,  3) = kIIR1Ltd( spcVec, Ind_('N2O5'), Ind_('SALACL'), &
                                       kITemp, HetMinLife)
         kITemp = HETN2O5_SS( XDenA, xRadi(12), xArea(12), TempK, clConc_SALC, 2)
         HET(ind_N2O5,  4) = kIIR1Ltd( spcVec, Ind_('N2O5'), Ind_('SALCCL'), &
                                       kITemp, HetMinLife)

         !----------------------------------------------------------------
         ! Reaction of OH with sea-salt Cl-, XW 3/12/18)
         !----------------------------------------------------------------
         kITemp = HETOH( XDenA, AClRADI, AClAREA, TempK, clConc_SALA)
         HET(ind_OH,  1) = kIIR1Ltd( spcVec, Ind_('OH'), Ind_('SALACL'), &
                                       kITemp, HetMinLife)
         kITemp = HETOH( XDenA, xRadi(12), xArea(12), TempK, clConc_SALC)
         HET(ind_OH,  2) = kIIR1Ltd( spcVec, Ind_('OH'), Ind_('SALCCL'), &
                                       kITemp, HetMinLife)

         !----------------------------------------------------------------
         ! Reaction of ClNO2 with sea-salt Cl-, XW 3/12/18)
         !----------------------------------------------------------------
         ! First consider reaction in troposphere cloud
         kITemp = HETClNO2_TCld( XDenA, rLiq, rIce, ALiq, AIce, VAir, TempK, &
                           pHCloud, clConc_CldA, clConc_CldC, clConc_Cldg, &
                           brConc_CldA, brConc_CldC, brConc_Cldg, 1)
         ! Then calculate reaction on aerosols out of cloud
         kITemp = kITemp + &
                  HETClNO2( XDenA, AClRADI, (1.0-CF)*AClAREA, SSAlk(1), &
                            TempK, pHSSA(1), clConc_SALA, brConc_SALA,1)

         HET(ind_ClNO2, 1) = kIIR1Ltd( spcVec, Ind_('ClNO2'), Ind_('SALACL'), &
                                       kITemp, HetMinLife)
 
         ! First consider reaction in troposphere cloud
         kITemp = HETClNO2_TCld( XDenA, rLiq, rIce, ALiq, AIce, VAir, TempK, &
                           pHCloud, clConc_CldA, clConc_CldC, clConc_Cldg, &
                           brConc_CldA, brConc_CldC, brConc_Cldg, 2)
         ! not on SALC

         HET(ind_ClNO2, 2) = kIIR1Ltd( spcVec, Ind_('ClNO2'), Ind_('SALCCL'), &
                                       kITemp, HetMinLife)        
 
         !----------------------------------------------------------------
         ! ClNO2 + dissolved HCl in cloud
         !----------------------------------------------------------------
         kITemp = HETClNO2_TCld( XDenA, rLiq, rIce, ALiq, AIce, VAir, TempK, &
                           pHCloud, clConc_CldA, clConc_CldC, clConc_Cldg, &
                           brConc_CldA, brConc_CldC, brConc_Cldg, 3)
         HET(ind_ClNO2, 3) = kIIR1Ltd( spcVec, Ind_('ClNO2'), Ind_('HCl'), &
                                       kITemp, HetMinLife)

         !----------------------------------------------------------------
         ! Reaction of ClNO2 with sea-salt Br-, XW 8/8/18)
         !----------------------------------------------------------------
         ! First consider reaction in troposphere cloud
         kITemp = HETClNO2_TCld( XDenA, rLiq, rIce, ALiq, AIce, VAir, TempK, &
                           pHCloud, clConc_CldA, clConc_CldC, clConc_Cldg, &
                           brConc_CldA, brConc_CldC, brConc_Cldg, 4)
         ! Then calculate reaction on aerosols out of cloud
         kITemp = kITemp + &
                  HETClNO2( XDenA, AClRADI, (1.0-CF)*AClAREA, SSAlk(1), &
                            TempK, pHSSA(1), clConc_SALA, brConc_SALA,2)

         HET(ind_ClNO2, 4) = kIIR1Ltd( spcVec, Ind_('ClNO2'), Ind_('BrSALA'), &
                                       kITemp, HetMinLife)

         ! First consider reaction in troposphere cloud
         kITemp = HETClNO2_TCld( XDenA, rLiq, rIce, ALiq, AIce, VAir, TempK, &
                           pHCloud, clConc_CldA, clConc_CldC, clConc_Cldg, &
                           brConc_CldA, brConc_CldC, brConc_Cldg, 5)
         ! Then calculate reaction on aerosols out of cloud
         kITemp = kITemp + &
                  HETClNO2( XDenA, xRadi(12), (1.0-CF)*xArea(12), SSAlk(2), &
                            TempK, pHSSA(2), clConc_SALC, brConc_SALC,2)
      
         HET(ind_ClNO2, 5) = kIIR1Ltd( spcVec, Ind_('ClNO2'), Ind_('BrSALC'), &
                                       kITemp, HetMinLife)

         !----------------------------------------------------------------
         ! ClNO2 + dissolved HBr in cloud
         !----------------------------------------------------------------
         kITemp = HETClNO2_TCld( XDenA, rLiq, rIce, ALiq, AIce, VAir, TempK, &
                           pHCloud, clConc_CldA, clConc_CldC, clConc_Cldg, &
                           brConc_CldA, brConc_CldC, brConc_Cldg, 6)
         HET(ind_ClNO2, 6) = kIIR1Ltd( spcVec, Ind_('ClNO2'), Ind_('HBr'), &
                                       kITemp, HetMinLife)

      ENDIF

      ! Iodine chemistry
      IF (Ind_('I2').gt.0) THEN

         ! Uptake reactions (forming AERI, ISALA and ISALC)
         HET(ind_HI,   1) = HETIUptake( MW_HI,   0.10e+0_fp,  8 )
         HET(ind_HI,   2) = HETIUptake( MW_HI,   0.10e+0_fp, 11 )
         HET(ind_HI,   3) = HETIUptake( MW_HI,   0.10e+0_fp, 12 )
         HET(ind_I2O2, 1) = HETIUptake( MW_I2O2, 0.02e+0_fp,  8 )
         HET(ind_I2O2, 2) = HETIUptake( MW_I2O2, 0.02e+0_fp, 11 )
         HET(ind_I2O2, 3) = HETIUptake( MW_I2O2, 0.02e+0_fp, 12 )
         HET(ind_I2O3, 1) = HETIUptake( MW_I2O3, 0.02e+0_fp,  8 )
         HET(ind_I2O3, 2) = HETIUptake( MW_I2O3, 0.02e+0_fp, 11 )
         HET(ind_I2O3, 3) = HETIUptake( MW_I2O3, 0.02e+0_fp, 12 )
         HET(ind_I2O4, 1) = HETIUptake( MW_I2O4, 0.02e+0_fp,  8 )
         HET(ind_I2O4, 2) = HETIUptake( MW_I2O4, 0.02e+0_fp, 11 )
         HET(ind_I2O4, 3) = HETIUptake( MW_I2O4, 0.02e+0_fp, 12 )

         ! These uptake reactions require non-acidic aerosol
         ! Fine sea salt first
         IF (SSAlk(1).gt.0.05) THEN
            HET(ind_HOI,  1) = HETIUptake( MW_HOI,   0.01e+0_fp, 11 )
            HET(ind_IONO, 1) = HETIUptake( MW_IONO,  0.02e+0_fp, 11 )
            HET(ind_IONO2,1) = HETIUptake( MW_IONO2, 0.01e+0_fp, 11 )
         ENDIF

         ! Now coarse sea salt
         IF (SSAlk(2).gt.0.05) THEN
            HET(ind_HOI,  2) = HETIUptake( MW_HOI,   0.01e+0_fp, 12 )
            HET(ind_IONO, 2) = HETIUptake( MW_IONO,  0.02e+0_fp, 12 )
            HET(ind_IONO2,2) = HETIUptake( MW_IONO2, 0.01e+0_fp, 12 )
         ENDIF

         ! Breakdown of iodine compounds on sea-salt
         HET(ind_HOI,  3) = HETIXCycleSSA( MW_HOI,   0.01E+0_fp, SSAlk, 1 )
         kITemp = HETIXCycleSSA( MW_HOI,   0.01E+0_fp, SSAlk, 2 )
         HET(ind_HOI,  4) = kIIR1Ltd( spcVec, Ind_('HOI'), Ind_('SALACL'), &
                                       kITemp, HetMinLife )
         kITemp = HETIXCycleSSA( MW_HOI,   0.01E+0_fp, SSAlk, 3 )
         HET(ind_HOI,  5) = kIIR1Ltd( spcVec, Ind_('HOI'), Ind_('SALCCL'), &
                                       kITemp, HetMinLife )
         HET(ind_IONO, 3) = HETIXCycleSSA( MW_IONO,  0.02E+0_fp, SSAlk, 1 )
         kITemp = HETIXCycleSSA( MW_IONO,   0.02E+0_fp, SSAlk, 2 )
         HET(ind_IONO, 4) = kIIR1Ltd( spcVec, Ind_('IONO'), Ind_('SALACL'), &
                                       kITemp, HetMinLife )
         kITemp = HETIXCycleSSA( MW_IONO,   0.02E+0_fp, SSAlk, 3 )
         HET(ind_IONO, 5) = kIIR1Ltd( spcVec, Ind_('IONO'), Ind_('SALCCL'), &
                                       kITemp, HetMinLife )
         HET(ind_IONO2,3) = HETIXCycleSSA( MW_IONO2, 0.01E+0_fp, SSAlk, 1 )
         kITemp = HETIXCycleSSA( MW_IONO2,  0.01E+0_fp, SSAlk, 2 )
         HET(ind_IONO2, 4) = kIIR1Ltd( spcVec, Ind_('IONO2'), Ind_('SALACL'), &
                                       kITemp, HetMinLife )
         kITemp = HETIXCycleSSA( MW_IONO2,  0.01E+0_fp, SSAlk, 3 )
         HET(ind_IONO2, 5) = kIIR1Ltd( spcVec, Ind_('IONO2'), Ind_('SALCCL'), &
                                       kITemp, HetMinLife )
         
      ENDIF

      SCF = SCF2

      ! Nullify pointers
      NULLIFY( spcVec )

      RETURN

    END SUBROUTINE SET_HET
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: kiir1ltd
!
! !DESCRIPTION: Determine removal rates for both species in an uptake reaction.
!\\
!\\
! !INTERFACE:
!
    FUNCTION kIIR1Ltd( spcVec, indGas, indEduct, kISource, minLife ) &
       RESULT( kII )
!
! !INPUT PARAMETERS: 
!
      ! Rate coefficients
      REAL(fp), INTENT(IN)           :: spcVec(:)
      INTEGER,  INTENT(IN)           :: indGas
      INTEGER,  INTENT(IN)           :: indEduct
      REAL(fp), INTENT(IN)           :: kISource
      REAL(fp), INTENT(IN), OPTIONAL :: minLife
!
! !RETURN VALUE:
!
      REAL(fp)                       :: kII
!
! !REMARKS:
!
! !REVISION HISTORY:
!  29 Mar 2016 - R. Yantosca - Added ProTeX header
!  01 Apr 2016 - R. Yantosca - Define N, XSTKCF, ADJUSTEDRATE locally
!  01 Apr 2016 - R. Yantosca - Replace KII_KI with DO_EDUCT local variable
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      REAL(fp) :: kIGas, kIEduct, concGas, concEduct
      REAL(fp) :: lifeA, lifeB, kIMult

      concGas = spcVec(indGas)
      concEduct = spcVec(indEduct)

      ! Copy kI as calculated assuming no limitation
      kIGas = kISource
      kIEduct = 0.0e+0_fp
      kII = 0.0e+0_fp

      IF (concEduct.lt.100.0e+0_fp) THEN
         kIGas = 0.0e+0_fp
         kIEduct = 0.0e+0_fp
         kII = 0.0e+0_fp
      ELSE
         ! Safe division here is probably overkill - may remove this
         IF (Is_Safe_Div(concGas*kIGas,concEduct)) THEN
            kIEduct = kIGas*concGas/concEduct
            kII = kIGas/concEduct
         ELSE
            kIGas = 0.0e+0_fp
            kIEduct = 0.0e+0_fp
            kII = 0.0e+0_fp
         ENDIF
      ENDIF

      ! Enforce a minimum lifetime?
      IF (PRESENT(minLife)) THEN
         IF ((kIGas.gt.0.0e+0_fp).and.(minLife.gt.0.0e+0_fp)) THEN
            ! Calculate lifetime of each reactant against removal
            lifeA = Safe_Div(1.0e+0_fp,kIGas,0.0e+0_fp)
            lifeB = Safe_Div(1.0e+0_fp,kIEduct,0.0e+0_fp)
            ! Check if either lifetime is "too short"
            IF ((lifeA.lt.lifeB).and.(lifeA.lt.minLife)) THEN
               IF (Is_Safe_Div(concGas*kIGas,concEduct)) THEN
                  kIGas = 1.0e+0_fp/minLife
                  kII = kIGas/concEduct
               ELSE
                  kIGas = 0.0e+0_fp
                  kII = 0.0e+0_fp
               ENDIF
            ELSEIF (lifeB.lt.minLife) THEN
               IF (Is_Safe_Div(concEduct*kIEduct,concGas)) THEN
                  kIEduct = 1.0e+0_fp/minLife
                  kII = kIEduct/concGas
               ELSE
                  kIEduct = 0.0e+0_fp
                  kII = 0.0e+0_fp
               ENDIF
            ENDIF
         ENDIF    
      ENDIF    
 
    END FUNCTION kIIR1Ltd
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: kiir1r2l
!
! !DESCRIPTION: Determine removal rates for both species in an uptake reaction
! without assuming which reactant is limiting.
!\\
!\\
! !INTERFACE:
!
    FUNCTION kIIR1R2L( spcVec, indGasA, indGasB, kIASource, kIBSource ) &
       RESULT( kII )
!
! !USES:
!
      !USE Error_Mod, ONLY: Is_Safe_Div
!
! !INPUT PARAMETERS: 
!
      ! Rate coefficients
      REAL(fp), INTENT(IN)    :: spcVec(:)
      INTEGER,  INTENT(IN)    :: indGasA
      INTEGER,  INTENT(IN)    :: indGasB
      REAL(fp), INTENT(IN)    :: kIASource
      REAL(fp), INTENT(IN)    :: kIBSource
!
! !RETURN VALUE:
!
      REAL(fp)                :: kII

!
! !REMARKS:
!
! !REVISION HISTORY:
!  29 Mar 2016 - R. Yantosca - Added ProTeX header
!  01 Apr 2016 - R. Yantosca - Define N, XSTKCF, ADJUSTEDRATE locally
!  01 Apr 2016 - R. Yantosca - Replace KII_KI with DO_EDUCT local variable
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      REAL(fp) :: concGasA, concGasB, kIA, kIB
      REAL(fp) :: R_GasA, R_GasB
      LOGICAL  :: nonZeroRate

      ! Get the base concentrations
      concGasA = spcVec(indGasA)
      concGasB = spcVec(indGasB)

      ! Copy the first estimates of kI for each species
      kIA = kIASource
      kIB = kIBSource
 
      ! Assume for now that the reaction will not proceed
      nonZeroRate = .False.
      kII = 0.0e+0_fp

      ! Prevent reaction if either concentration is too low
      IF ((concGasA.gt.100.0e+0_fp).and.(concGasB.gt.100.0e+0_fp).and.&
          (kIA.gt.0.0e+0_fp).and.(kIB.gt.0.0e+0_fp)) THEN
         ! Calculate the overall rate based on each reactant
         R_GasA = kIA*concGasA
         R_GasB = kIB*concGasB
         IF (R_GasA > R_GasB) THEN
            ! Limited by uptake of B
            nonZeroRate = Is_Safe_Div( R_GasB, concGasA )
            IF (nonZeroRate) THEN
               kII = kIB / concGasA
            ENDIF
         ELSE
            ! Limited by uptake of A
            nonZeroRate = Is_Safe_Div( R_GasA, concGasB )
            IF (nonZeroRate) THEN
               kII = kIA / concGasB
            ENDIF
         ENDIF
      ENDIF

      ! If no tests were passed, zero out both rates
      IF (.not.nonZeroRate) THEN
         kII = 0.0e+0_fp
      ENDIF

    END FUNCTION kIIR1R2L
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetIXCycleSSA
!
! !DESCRIPTION: Set the iodine reaction rate on sea salt, assuming a fixed ratio
! of ICl and IBr (85:15) is produced.
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETIXCycleSSA( A, B, SSAlk, X ) RESULT( kISum )
!
! !INPUT PARAMETERS: 
!
      ! Rate coefficients
      REAL(fp), INTENT(IN) :: A, B
      ! Sea salt alkalinity
      REAL(fp), INTENT(IN) :: SSAlk(2)
      ! Br or Cl
      INTEGER, INTENT(IN) :: X
!
! !RETURN VALUE:
! 
      REAL(fp)             :: kISum
!
! !REMARKS:
!
! !REVISION HISTORY:
!  24 Dec 2016 - S. D. Eastham - Initial version
!  04 Apr 2018 - X. Wang       - Update for Cl- simulation
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      REAL(fp) :: XSTKCF, ADJUSTEDRATE, r_gp
      INTEGER  :: N, NAer, N1, N2

      ! Initialize
      kISum        = 0.0_fp

      IF (X == 1) THEN
         !for Br SALA+SALC
         N1 = 1
         N2 = 2      
         r_gp = 0.15e+0_fp
      ELSEIF (X == 2) THEN
         !for SALACl
         N1 = 1
         N2 = 1
         r_gp = 0.85e+0_fp
      ELSEIF (X == 3) THEN
         !for SALCCl
         N1 = 2
         N2 = 2
         r_gp = 0.85e+0_fp
      ENDIF


      DO N = N1, N2
         NAer = N + 10
         ! Only allow reaction on acidic aerosol
         IF (SSAlk(N).le.0.05e+0_fp) THEN
            ! Reaction rate for surface of aerosol
            AdjustedRate = ARSL1K(XAREA(NAer),XRADI(NAer),XDENA,B,XTEMP,(A**0.5_fp))
            kISum = kISum + AdjustedRate * r_gp
         ENDIF
      ENDDO
      
    END FUNCTION HETIXCycleSSA
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetIUptake
!
! !DESCRIPTION: Set the uptake rate for iodine species.
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETIUptake( A, B, N ) RESULT( kISum )
!
! !INPUT PARAMETERS: 
!
      ! Rate coefficients
      REAL(fp), INTENT(IN) :: A, B
      ! Which aerosol?
      INTEGER,  INTENT(IN) :: N
!
! !RETURN VALUE:
! 
      REAL(fp)             :: kISum
!
! !REMARKS:
!
! !REVISION HISTORY:
!  24 Dec 2016 - S. D. Eastham - Initial version
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      !REAL(fp) :: XSTKCF, ADJUSTEDRATE

      ! Initialize
      kISum        = 0.0_fp

      ! Reaction rate for surface of aerosol
      kISum = ARSL1K(XAREA(N),XRADI(N),XDENA,B,XTEMP,(A**0.5_fp))
#if defined( UCX )
      ! Also allow reaction on stratospheric sulfate (N=13) if 
      ! tropospheric sulfate is requested (N=8)
      IF (N.eq.8) THEN
         kISum = kISum + ARSL1K(XAREA(13),XRADI(13),XDENA,B,XTEMP, &
                               (A**0.5_fp))
      ENDIF
#endif
      
    END FUNCTION HETIUptake
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetNO3
!
! !DESCRIPTION: Set the heterogenous chemistry rate for NO3.
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETNO3( A, B ) RESULT( HET_NO3 )
!
! !INPUT PARAMETERS: 
!
      ! Rate coefficients
      REAL(fp), INTENT(IN) :: A, B
!
! !RETURN VALUE:
!
      REAL(fp)             :: HET_NO3
!
! !REMARKS:
!
! !REVISION HISTORY:
!  29 Mar 2016 - R. Yantosca - Added ProTeX header
!  01 Apr 2016 - R. Yantosca - Define N, XSTKCF, ADJUSTEDRATE locally
!  01 Apr 2016 - R. Yantosca - Replace KII_KI with DO_EDUCT local variable
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      LOGICAL  :: DO_EDUCT
      INTEGER  :: N
      REAL(fp) :: XSTKCF, ADJUSTEDRATE

      ! Initialize
      HET_NO3      = 0.0_fp
      ADJUSTEDRATE = 0.0_fp
      XSTKCF       = 0.0_fp

      ! Don't do PSC rate adjustment
      DO_EDUCT     = .FALSE.

      ! Loop over aerosol types
      DO N = 1, NAERO

         XSTKCF = B

         IF (N.eq.13) THEN
            ! Calculate for stratospheric liquid aerosol
            ! Note that XSTKCF is actually a premultiplying
            ! factor in this case, including c-bar
            ADJUSTEDRATE = XAREA(N) * XSTKCF
         ELSEIF ((N.eq.11).or.(N.eq.12).or.(N.eq.8)) THEN
            ! Follow combined hydrolysis with Cl-, xnw
            ADJUSTEDRATE = 0.0e0_fp
         ELSE
            ! Reaction rate for surface of aerosol
            ADJUSTEDRATE=ARSL1K(XAREA(N),XRADI(N),XDENA,XSTKCF,XTEMP, &
                               (A**0.5_FP))
         ENDIF
         
         IF ( DO_EDUCT .and. N > 12 ) THEN
            ! PSC reaction - prevent excessive reaction rate
            IF (ADJUSTEDRATE.gt.(1.e+0_fp/HetMinLife)) THEN
               ADJUSTEDRATE = 1.e+0_fp/HetMinLife
            ENDIF
         ENDIF
         
         ! Add to overall reaction rate
         HET_NO3 = HET_NO3 + ADJUSTEDRATE

      ENDDO
      
    END FUNCTION HETNO3
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetNO2
!
! !DESCRIPTION: Set the heterogenous chemistry rate for NO2.
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETNO2( A, B ) RESULT( HET_NO2 )
!
! !INPUT PARAMETERS: 
!
      ! Rate coefficients
      REAL(fp), INTENT(IN) :: A, B
!
! !RETURN VALUE:
! 
      REAL(fp)             :: HET_NO2
!
! !REMARKS:
!
! !REVISION HISTORY:
!  29 Mar 2016 - R. Yantosca - Added ProTeX header
!  01 Apr 2016 - R. Yantosca - Define N, XSTKCF, ADJUSTEDRATE locally
!  01 Apr 2016 - R. Yantosca - Replace KII_KI with DO_EDUCT local variable
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      LOGICAL  :: DO_EDUCT
      INTEGER  :: N
      REAL(fp) :: XSTKCF, ADJUSTEDRATE

      ! Initialize
      HET_NO2      = 0.0_fp
      ADJUSTEDRATE = 0.0_fp
      XSTKCF       = 0.0_fp

      ! Don't do PSC rate adjustment
      DO_EDUCT     = .FALSE.

      ! Loop over aerosol types
      DO N = 1, NAERO

         XSTKCF = B

         IF (N.eq.13) THEN
            ! Calculate for stratospheric liquid aerosol
            ! Note that XSTKCF is actually a premultiplying
            ! factor in this case, including c-bar
            ADJUSTEDRATE = XAREA(N) * XSTKCF
         ELSE
            ! Reaction rate for surface of aerosol
            ADJUSTEDRATE=ARSL1K(XAREA(N),XRADI(N),XDENA,XSTKCF,XTEMP, &
                               (A**0.5_fp))
         ENDIF
         
         IF ( DO_EDUCT .and. N > 12 ) THEN
            ! PSC reaction - prevent excessive reaction rate
            IF (ADJUSTEDRATE.gt.(1.e+0_fp/HetMinLife)) THEN
               ADJUSTEDRATE = 1.e+0_fp/HetMinLife
            ENDIF
         ENDIF
         
         ! Add to overall reaction rate
         HET_NO2 = HET_NO2 + ADJUSTEDRATE

      END DO
      
    END FUNCTION HETNO2
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetHO2
!
! !DESCRIPTION: Set the heterogenous chemistry rate for HO2.
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETHO2( A, B ) RESULT( HET_HO2 )
!
! !INPUT PARAMETERS:
!
      ! Rate coefficients
      REAL(fp), INTENT(IN) :: A, B
!
! !RETURN VALUE:
!
      REAL(fp)             :: HET_HO2
!
! !REMARKS:
!
! !REVISION HISTORY:
!  29 Mar 2016 - R. Yantosca - Added ProTeX headers
!  01 Apr 2016 - R. Yantosca - Define N, XSTKCF, ADJUSTEDRATE locally
!  01 Apr 2016 - R. Yantosca - Replace KII_KI with DO_EDUCT local variable
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      LOGICAL  :: DO_EDUCT
      INTEGER  :: N
      REAL(fp) :: XSTKCF, ADJUSTEDRATE

      ! Initialize
      HET_HO2      = 0.0_fp
      ADJUSTEDRATE = 0.0_fp
      XSTKCF       = 0.0_fp

      ! Don't do PSC rate adjustment
      DO_EDUCT     = .FALSE.

      ! Loop over aerosol types
      DO N = 1, NAERO

         XSTKCF = 0e+0_fp
         IF (N.gt.12) THEN
            XSTKCF = TINY(1e+0_fp)
         ELSE
            XSTKCF = GAMMA_HO2
         ENDIF

         IF (N.eq.13) THEN
            ! Calculate for stratospheric liquid aerosol
            ! Note that XSTKCF is actually a premultiplying
            ! factor in this case, including c-bar
            ADJUSTEDRATE = XAREA(N) * XSTKCF
         ELSE
            ! Reaction rate for surface of aerosol
            ADJUSTEDRATE=ARSL1K(XAREA(N),XRADI(N),XDENA,XSTKCF,XTEMP, &
                               (A**0.5_FP))
         ENDIF
         
         IF ( DO_EDUCT .and. N > 12 ) THEN
            ! PSC reaction - prevent excessive reaction rate
            IF (ADJUSTEDRATE.gt.(1.e+0_fp/HetMinLife)) THEN
               ADJUSTEDRATE = 1.e+0_fp/HetMinLife
            ENDIF
         ENDIF
         
         ! Add to overall reaction rate
         HET_HO2 = HET_HO2 + ADJUSTEDRATE

      ENDDO

    END FUNCTION HETHO2
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetHBr
!
! !DESCRIPTION: Set the heterogeneous rate for HBr.
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETHBr( A, B ) RESULT( HET_HBr )
!
! !INPUT PARAMETERS: 
!
      ! Rate coefficients
      REAL(fp), INTENT(IN) :: A, B
!
! !RETURN VALUE:
!
      REAL(fp)             :: HET_HBr
!
! !REMARKS:
!
! !REVISION HISTORY:
!  29 Mar 2016 - R. Yantosca - Added ProTeX headers
!  01 Apr 2016 - R. Yantosca - Define N, XSTKCF, ADJUSTEDRATE locally
!  01 Apr 2016 - R. Yantosca - Define local variable for educt adjustment
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      LOGICAL  :: DO_EDUCT
      INTEGER  :: N
      REAL(fp) :: XSTKCF, ADJUSTEDRATE

      ! Initialize
      HET_HBr      = 0.0_fp
      ADJUSTEDRATE = 0.0_fp
      XSTKCF       = 0.0_fp

      ! Only apply PSC rate adjustment if at high altitude
      DO_EDUCT     = STRATBOX

      ! Loop over aerosol types
      DO N = 1, NAERO

         ! jpp, 3/22/11: set the sticking coefficient to 
         !  ~0 for aerosol types we don't want reactions on
         !  for the HBr and HOBr surface reaction
         XSTKCF = 0e+0_fp         
         ! Select proper aerosol type
         IF ( (N == 8) .OR. (N == 11) .OR. (N == 12)) THEN
            ! sulfate, 2 modes of sea-salt
            XSTKCF = B
         ELSEIF ( N == 13 ) THEN
            XSTKCF = KHETI_SLA(11)
         ELSEIF ( N == 14 ) THEN
            XSTKCF = 0.1e+0_fp
         ELSE
            XSTKCF = 0e+0_fp
         ENDIF

         IF (N.eq.13) THEN
            ! Calculate for stratospheric liquid aerosol
            ! Note that XSTKCF is actually a premultiplying
            ! factor in this case, including c-bar
            ADJUSTEDRATE = XAREA(N) * XSTKCF
         ELSE
            ! Reaction rate for surface of aerosol
            ADJUSTEDRATE=ARSL1K(XAREA(N),XRADI(N),XDENA,XSTKCF,XTEMP, &
                               (A**0.5_FP))
         ENDIF

         scf2(2) = xstkcf

         IF ( DO_EDUCT .and. N > 12 ) THEN
            ! PSC reaction - prevent excessive reaction rate
            IF (ADJUSTEDRATE.gt.(1.e+0_fp/HetMinLife)) THEN
               ADJUSTEDRATE = 1.e+0_fp/HetMinLife
            ENDIF
         ENDIF

         ! Add to overall reaction rate
         HET_HBr = HET_HBr + ADJUSTEDRATE

      ENDDO

    END FUNCTION HETHBr
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetN2O5
!
! !DESCRIPTION: Set heterogenous chemistry rate for N2O5.
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETN2O5( A, B, C_X1, C_X2) RESULT( HET_N2O5 )
!
! !INPUT PARAMETERS: 
!
      ! Rate coefficients
      REAL(fp), INTENT(IN) :: A, B
      ! Cl- concentration (mol/L)
      REAL(fp), INTENT(IN) :: C_X1, C_X2
!
! !RETURN VALUE:
!
      REAL(fp)             :: HET_N2O5
!
! !REMARKS:
!
! !REVISION HISTORY:
!  29 Mar 2016 - R. Yantosca - Added ProTeX header
!  01 Apr 2016 - R. Yantosca - Define N, XSTKCF, ADJUSTEDRATE locally
!  01 Apr 2016 - R. Yantosca - Replace KII_KI with DO_EDUCT local variable
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      LOGICAL  :: DO_EDUCT
      INTEGER  :: N
      REAL(fp) :: XSTKCF, ADJUSTEDRATE
      REAL(fp) :: TMP1,   TMP2
      REAL(fp) :: GAM_N2O5, r_gp
   
      ! Initialize
      HET_N2O5     = 0.0_fp
      ADJUSTEDRATE = 0.0_fp
      XSTKCF       = 0.0_fp
      TMP1         = 0.0_fp
      TMP2         = 0.0_fp
      GAM_N2O5     = 0.0_fp
      r_gp         = 1.0_fp

      ! Always apply PSC rate adjustment
      DO_EDUCT     = .TRUE.

      ! Loop over aerosol types
      DO N = 1, NAERO

         XSTKCF = 0e+0_fp
         ! Get GAMMA for N2O5 hydrolysis, which is
         ! a function of aerosol type, temp, and RH
         IF (N.eq.14) THEN
            IF (NATSURFACE) THEN
               XSTKCF = 4.0e-4_fp ! NAT
            ELSE
               XSTKCF = 0.02e+0_fp ! Ice
            ENDIF
         ELSEIF (N.eq.13) THEN
            ! Stratospheric aerosol
            XSTKCF = KHETI_SLA(1)
         ELSEIF (N.eq.11) THEN
            ! Sea salt - follows the N2O5 + Cl- channel by xnw
            CALL GAMMA_N2O5_Cl(C_X1, RELHUM, 1, Gam_N2O5, r_gp)
            XSTKCF = GAM_N2O5
         ELSEIF (N.eq.12) THEN
            ! Sea salt - follows the N2O5 + Cl- channel by xnw
            CALL GAMMA_N2O5_Cl(C_X2, RELHUM, 2, Gam_N2O5, r_gp)
            XSTKCF = GAM_N2O5
	 ! restore route for tropospheric sulfate (tms 17/04/10)
	 ! this is to maintain consistancy with Sherwen et al (2016)
         ELSEIF (N.eq.8) THEN
            ! Fixed gamma?
            !XSTKCF = 0.1e-4_fp ! Sulfate
            ! RH dependence
            !XSTKCF = N2O5( N, TEMPK, RELHUM )
            ! Sulfate - follows the N2O5 + Cl- channel by xnw
            XSTKCF = 0.0e+0_fp
         ELSE
            ! In UCX, ABSHUMK will have been set by
            ! STT(I,J,L,IDTH2O)
            XSTKCF = N2O5( N, TEMPK, RELHUM )
         ENDIF

         IF (N.eq.13) THEN
            ! Calculate for stratospheric liquid aerosol
            ! Note that XSTKCF is actually a premultiplying
            ! factor in this case, including c-bar
            ADJUSTEDRATE = XAREA(N) * XSTKCF
         ELSEIF (N.eq.11) THEN
            ADJUSTEDRATE=ARSL1K(AClAREA,AClRADI,XDENA,XSTKCF,XTEMP, &
                               (A**0.5_FP)) * (1.0e0_fp-r_gp)
         ELSEIF (N.eq.12) THEN
            ADJUSTEDRATE=ARSL1K(XAREA(N),XRADI(N),XDENA,XSTKCF,XTEMP, &
                               (A**0.5_FP)) * (1.0e0_fp-r_gp)
         ELSE
            ! Reaction rate for surface of aerosol
            ADJUSTEDRATE=ARSL1K(XAREA(N),XRADI(N),XDENA,XSTKCF,XTEMP, &
                               (A**0.5_FP))
         ENDIF
         
         ! Add to overall reaction rate
         HET_N2O5 = HET_N2O5 + ADJUSTEDRATE

      END DO

    END FUNCTIOn HETN2O5
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetGLYX
!
! !DESCRIPTION: Sets the heterogenous chemistry rate for GLYX.
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETGLYX( A, B ) RESULT( HET_GLYX )
!
! !INPUT PARAMETERS: 
!
      ! Rate coefficients
      REAL(fp), INTENT(IN) :: A, B
!
! !RETURN VALUE:
!
      REAL(fp)             :: HET_GLYX
!
! !REMARKS:
!
! !REVISION HISTORY:
!  15 Jun 2017 - M. Sulprizio- Initial version based on calcrate.F from E.Marais
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      LOGICAL  :: DO_EDUCT
      INTEGER  :: N
      REAL(fp) :: XSTKCF, ADJUSTEDRATE

      ! Initialize
      HET_GLYX     = 0.0_fp
      ADJUSTEDRATE = 0.0_fp
      XSTKCF       = 0.0_fp

      ! Don't do PSC rate adjustment
      DO_EDUCT     = .FALSE.

      ! Loop over aerosol types
      DO N = 1, NAERO

         ! Default value
         XSTKCF = TINY(1e+0_fp)

         ! Only consider inorganic aqueous aerosols with RH > 35%.
         ! Uptake during the day (higher uptake than night)
         ! (Sumner et al., 2014):
         IF ( N == 8 .and. RELHUM >= CRITRH ) THEN

            ! Define gamma for GLYX:
            IF ( SUNCOS .gt. 0 ) THEN

               ! Uptake during the day (use Liggio et al., 2005):
               XSTKCF = 2.9e-3_fp

            ELSE

               ! Uptake at night (lower uptake than day)
               ! Value is within the range 1d-5 to 1d-6
               ! (Faye McNeill personal communication, eam, 2015):
               XSTKCF = 5.0e-6_fp

            ENDIF

         ENDIF

         IF (N.eq.13) THEN
            ! Calculate for stratospheric liquid aerosol
            ! Note that XSTKCF is actually a premultiplying
            ! factor in this case, including c-bar
            ADJUSTEDRATE = XAREA(N) * XSTKCF
         ELSE
            ! Reaction rate for surface of aerosol
            ADJUSTEDRATE=ARSL1K(XAREA(N),XRADI(N),XDENA,XSTKCF,XTEMP, &
                               (A**0.5_FP))
         ENDIF

         IF ( DO_EDUCT .and. N > 12 ) THEN
            ! PSC reaction - prevent excessive reaction rate
            IF (ADJUSTEDRATE.gt.(1.e+0_fp/HetMinLife)) THEN
               ADJUSTEDRATE = 1.e+0_fp/HetMinLife
            ENDIF
         ENDIF
         
         ! Add to overall reaction rate
         HET_GLYX = HET_GLYX + ADJUSTEDRATE
      END DO

    END FUNCTIOn HETGLYX
!EOC
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetMGLY
!
! !DESCRIPTION: Sets the heterogenous chemistry rate for MGLY.
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETMGLY( A, B ) RESULT( HET_MGLY )
!
! !INPUT PARAMETERS: 
!
      ! Rate coefficients
      REAL(fp), INTENT(IN) :: A, B
!
! !RETURN VALUE:
!
      REAL(fp)             :: HET_MGLY
!
! !REMARKS:
!
! !REVISION HISTORY:
!  15 Jun 2017 - M. Sulprizio- Initial version based on calcrate.F from E.Marais
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      LOGICAL  :: DO_EDUCT
      INTEGER  :: N
      REAL(fp) :: XSTKCF, ADJUSTEDRATE

      ! Initialize
      HET_MGLY     = 0.0_fp
      ADJUSTEDRATE = 0.0_fp
      XSTKCF       = 0.0_fp

      ! Don't do PSC rate adjustment
      DO_EDUCT     = .FALSE.

      ! Loop over aerosol types
      DO N = 1, NAERO

         ! Default value
         XSTKCF = TINY(1e+0_fp)

         ! Only consider inorganic aqueous aerosols with RH > 35%.
         IF ( N == 8 .and. RELHUM >= CRITRH ) THEN

            ! Define gamma for MGLY:
            ! Obtained by scaling gamma GLYX by the
            ! ratio of effective Henry's law constants
            ! for GLYX (3d7) and MGLY (3.7d3) (eam, 02/2015):
            XSTKCF = 3.6e-7_fp

         ENDIF

         IF (N.eq.13) THEN
            ! Calculate for stratospheric liquid aerosol
            ! Note that XSTKCF is actually a premultiplying
            ! factor in this case, including c-bar
            ADJUSTEDRATE = XAREA(N) * XSTKCF
         ELSE
            ! Reaction rate for surface of aerosol
            ADJUSTEDRATE=ARSL1K(XAREA(N),XRADI(N),XDENA,XSTKCF,XTEMP, &
                               (A**0.5_FP))
         ENDIF

         IF ( DO_EDUCT .and. N > 12 ) THEN
            ! PSC reaction - prevent excessive reaction rate
            IF (ADJUSTEDRATE.gt.(1.e+0_fp/HetMinLife)) THEN
               ADJUSTEDRATE = 1.e+0_fp/HetMinLife
            ENDIF
         ENDIF
         
         ! Add to overall reaction rate
         HET_MGLY = HET_MGLY + ADJUSTEDRATE
      END DO

    END FUNCTIOn HETMGLY
!EOC
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetIEPOX
!
! !DESCRIPTION: Sets the heterogenous chemistry rate for IEPOX.
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETIEPOX( A, B ) RESULT( HET_IEPOX )
!
! !INPUT PARAMETERS: 
!
      ! Rate coefficients
      REAL(fp), INTENT(IN) :: A, B
!
! !RETURN VALUE:
!
      REAL(fp)             :: HET_IEPOX
!
! !REMARKS:
!
! !REVISION HISTORY:
!  15 Jun 2017 - M. Sulprizio- Initial version based on calcrate.F from E.Marais
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      LOGICAL  :: DO_EDUCT
      INTEGER  :: N
      REAL(fp) :: XSTKCF, ADJUSTEDRATE

      REAL(fp) :: HSTAR, K_HPLUS, K_NUC, K_HSO4, K_HYDRO

      ! Initialize
      HET_IEPOX    = 0.0_fp
      ADJUSTEDRATE = 0.0_fp
      XSTKCF       = 0.0_fp

      ! Don't do PSC rate adjustment
      DO_EDUCT     = .FALSE.

      ! Loop over aerosol types
      DO N = 1, NAERO

         ! Default value
         XSTKCF = TINY(1e+0_fp)

         ! Only consider inorganic aqueous aerosols with RH > 35%.
         IF ( N == 8 .and. RELHUM >= CRITRH ) THEN

            ! Define Henry's Law constant
            ! Changes H* for IEPOX again to accommodate
            ! reduction in yields of RIP, precursor
            ! of IEPOX (eam, 07/2015):
            HSTAR = HSTAR_EPOX    ! (Nguyen et al., 2014)

            ! Define first-order particle phase reaction rates 
            ! specific to IEPOX (from Gaston et al., 2014):
            K_HPLUS = 3.6e-2_fp   ! Alternate: 1.2d-3 (Edding)
            K_NUC   = 2.e-4_fp    ! Alternate: 5.2d-1 (Piletic)
            K_HSO4  = 7.3e-4_fp
            K_HYDRO = 0.0e+0_fp

            ! Get GAMMA for IEPOX hydrolysis:
            XSTKCF = EPOXUPTK( XAREA(N), XRADI(N),            &
                               TEMPK,    (A**0.5_fp),         &
                               HSTAR,    K_HPLUS,    H_PLUS,  &
                               K_NUC,    MSO4,       MNO3,    &
                               K_HSO4,   MHSO4,      K_HYDRO )

         ENDIF

         IF (N.eq.13) THEN
            ! Calculate for stratospheric liquid aerosol
            ! Note that XSTKCF is actually a premultiplying
            ! factor in this case, including c-bar
            ADJUSTEDRATE = XAREA(N) * XSTKCF
         ELSE
            ! Reaction rate for surface of aerosol
            ADJUSTEDRATE=ARSL1K(XAREA(N),XRADI(N),XDENA,XSTKCF,XTEMP, &
                               (A**0.5_FP))
         ENDIF

         IF ( DO_EDUCT .and. N > 12 ) THEN
            ! PSC reaction - prevent excessive reaction rate
            IF (ADJUSTEDRATE.gt.(1.e+0_fp/HetMinLife)) THEN
               ADJUSTEDRATE = 1.e+0_fp/HetMinLife
            ENDIF
         ENDIF
         
         ! Add to overall reaction rate
         HET_IEPOX = HET_IEPOX + ADJUSTEDRATE
      END DO

    END FUNCTIOn HETIEPOX
!EOC
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetIMAE
!
! !DESCRIPTION: Sets the heterogenous chemistry rate for IMAE.
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETIMAE( A, B ) RESULT( HET_IMAE )
!
! !INPUT PARAMETERS: 
!
      ! Rate coefficients
      REAL(fp), INTENT(IN) :: A, B
!
! !RETURN VALUE:
!
      REAL(fp)             :: HET_IMAE
!
! !REMARKS:
! Here use the same values as are read in for IEPOX, but scale down gamma by
! a factor of 30 to get the value for IMAE. Gamma for the two species are
! similar under neutral conditions, so use IEPOX gamma when [H+] <= 8d-5.
! Implemented by (eam, 01/2015) using lab study findings from Riedel et al.,
! EST, 2015.
!
! !REVISION HISTORY:
!  15 Jun 2017 - M. Sulprizio- Initial version based on calcrate.F from E.Marais
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      LOGICAL  :: DO_EDUCT
      INTEGER  :: N
      REAL(fp) :: XSTKCF, ADJUSTEDRATE

      REAL(fp) :: HSTAR, K_HPLUS, K_NUC, K_HSO4, K_HYDRO

      ! Initialize
      HET_IMAE     = 0.0_fp
      ADJUSTEDRATE = 0.0_fp
      XSTKCF       = 0.0_fp

      ! Don't do PSC rate adjustment
      DO_EDUCT     = .FALSE.

      ! Loop over aerosol types
      DO N = 1, NAERO

         ! Default value
         XSTKCF = TINY(1e+0_fp)

         ! Only consider inorganic aqueous aerosols with RH > 35%.
         IF ( N == 8 .and. RELHUM >= CRITRH ) THEN

            ! Define Henry's Law constant.
            ! Changes H* for IEPOX again to accommodate
            ! reduction in yields of RIP, precursor
            ! of IEPOX (eam, 07/2015):
            HSTAR = HSTAR_EPOX   ! (Nguyen et al., 2014)

            ! Define first-order particle phase reaction rates 
            ! specific to IEPOX (from Gaston et al., 2014):
            K_HPLUS = 3.6e-2_fp   ! Alternate: 1.2d-3 (Edding)
            K_NUC   = 2.6e-4_fp   ! Alternate: 5.2d-1 (Piletic)
            K_HSO4  = 7.3e-4_fp
            K_HYDRO = 0.e+0_fp

            ! Get GAMMA for IMAE hydrolysis:
            XSTKCF = EPOXUPTK( XAREA(N), XRADI(N),            &
                               TEMPK,    (A**0.5_fp),         &
                               HSTAR,    K_HPLUS,    H_PLUS,  &
                               K_NUC,    MSO4,       MNO3,    &
                               K_HSO4,   MHSO4,      K_HYDRO )

            ! Scale down gamma if H+ > 8d-5 (30x less than gamma for IEPOX)
            ! (Riedel et al., 2015)
            IF ( H_PLUS .gt. 8.e-5_fp ) THEN
               XSTKCF = XSTKCF / 30.e+0_fp
            ENDIF

         ENDIF

         IF (N.eq.13) THEN
            ! Calculate for stratospheric liquid aerosol
            ! Note that XSTKCF is actually a premultiplying
            ! factor in this case, including c-bar
            ADJUSTEDRATE = XAREA(N) * XSTKCF
         ELSE
            ! Reaction rate for surface of aerosol
            ADJUSTEDRATE=ARSL1K(XAREA(N),XRADI(N),XDENA,XSTKCF,XTEMP, &
                               (A**0.5_FP))
         ENDIF

         IF ( DO_EDUCT .and. N > 12 ) THEN
            ! PSC reaction - prevent excessive reaction rate
            IF (ADJUSTEDRATE.gt.(1.e+0_fp/HetMinLife)) THEN
               ADJUSTEDRATE = 1.e+0_fp/HetMinLife
            ENDIF
         ENDIF
         
         ! Add to overall reaction rate
         HET_IMAE = HET_IMAE + ADJUSTEDRATE
      END DO

    END FUNCTIOn HETIMAE
!EOC
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetLVOC
!
! !DESCRIPTION: Sets the heterogenous chemistry rate for LVOC: condensation of
! low-volatility ISOPOOH oxidation products.
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETLVOC( A, B ) RESULT( HET_LVOC )
!
! !INPUT PARAMETERS: 
!
      ! Rate coefficients
      REAL(fp), INTENT(IN) :: A, B
!
! !RETURN VALUE:
!
      REAL(fp)             :: HET_LVOC
!
! !REMARKS:
!
! !REVISION HISTORY:
!  15 Jun 2017 - M. Sulprizio- Initial version based on calcrate.F from E.Marais
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      LOGICAL  :: DO_EDUCT
      INTEGER  :: N
      REAL(fp) :: XSTKCF, ADJUSTEDRATE

      ! Initialize
      HET_LVOC     = 0.0_fp
      ADJUSTEDRATE = 0.0_fp
      XSTKCF       = 0.0_fp

      ! Don't do PSC rate adjustment
      DO_EDUCT     = .FALSE.

      ! Loop over aerosol types
      DO N = 1, NAERO

         ! Define gamma

         IF (N.eq.8 .and. RELHUM >= CRITRH) THEN
            XSTKCF = B
         ENDIF

         IF (N.eq.13) THEN
            ! Calculate for stratospheric liquid aerosol
            ! Note that XSTKCF is actually a premultiplying
            ! factor in this case, including c-bar
            ADJUSTEDRATE = XAREA(N) * XSTKCF
         ELSE
            ! Reaction rate for surface of aerosol
            ADJUSTEDRATE=ARSL1K(XAREA(N),XRADI(N),XDENA,XSTKCF,XTEMP, &
                               (A**0.5_FP))
         ENDIF

         IF ( DO_EDUCT .and. N > 12 ) THEN
            ! PSC reaction - prevent excessive reaction rate
            IF (ADJUSTEDRATE.gt.(1.e+0_fp/HetMinLife)) THEN
               ADJUSTEDRATE = 1.e+0_fp/HetMinLife
            ENDIF
         ENDIF
         
         ! Add to overall reaction rate
         HET_LVOC = HET_LVOC + ADJUSTEDRATE
      END DO

    END FUNCTIOn HETLVOC
!EOC
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetISN1OG
!
! !DESCRIPTION: Sets the heterogenous chemistry rate for ISN1OG: uptake of 2nd
! generation organic nitrates formed from ISOP+NO3 reaction (eam, 02/2015).
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETISN1OG( A, B ) RESULT( HET_ISN1OG )
!
! !INPUT PARAMETERS: 
!
      ! Rate coefficients
      REAL(fp), INTENT(IN) :: A, B
!
! !RETURN VALUE:
!
      REAL(fp)             :: HET_ISN1OG
!
! !REMARKS:
!
! !REVISION HISTORY:
!  15 Jun 2017 - M. Sulprizio- Initial version based on calcrate.F from E.Marais
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      LOGICAL  :: DO_EDUCT
      INTEGER  :: N
      REAL(fp) :: XSTKCF, ADJUSTEDRATE

      ! Initialize
      HET_ISN1OG   = 0.0_fp
      ADJUSTEDRATE = 0.0_fp
      XSTKCF       = 0.0_fp

      ! Don't do PSC rate adjustment
      DO_EDUCT     = .FALSE.

      ! Loop over aerosol types
      DO N = 1, NAERO

         ! Define gamma
         IF (N.eq.8 .and. RELHUM >= CRITRH) THEN
            XSTKCF = B
         ENDIF

         IF (N.eq.13) THEN
            ! Calculate for stratospheric liquid aerosol
            ! Note that XSTKCF is actually a premultiplying
            ! factor in this case, including c-bar
            ADJUSTEDRATE = XAREA(N) * XSTKCF
         ELSE
            ! Reaction rate for surface of aerosol
            ADJUSTEDRATE=ARSL1K(XAREA(N),XRADI(N),XDENA,XSTKCF,XTEMP, &
                               (A**0.5_FP))
         ENDIF

         IF ( DO_EDUCT .and. N > 12 ) THEN
            ! PSC reaction - prevent excessive reaction rate
            IF (ADJUSTEDRATE.gt.(1.e+0_fp/HetMinLife)) THEN
               ADJUSTEDRATE = 1.e+0_fp/HetMinLife
            ENDIF
         ENDIF
         
         ! Add to overall reaction rate
         HET_ISN1OG = HET_ISN1OG + ADJUSTEDRATE
      END DO

    END FUNCTIOn HETISN1OG
!EOC
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetISOPND
!
! !DESCRIPTION: Sets the heterogenous chemistry rate for ISOPND.
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETISOPND( A, B ) RESULT( HET_ISOPND )
!
! !INPUT PARAMETERS: 
!
      ! Rate coefficients
      REAL(fp), INTENT(IN) :: A, B
!
! !RETURN VALUE:
!
      REAL(fp)             :: HET_ISOPND
!
! !REMARKS:
!
! !REVISION HISTORY:
!  15 Jun 2017 - M. Sulprizio- Initial version based on calcrate.F from E.Marais
!  14 Jul 2017 - M. Sulprizio- Product has been changed to IONITA, which also
!                              has heterogeneous reaction. Remove call to
!                              EPOXUPTK here and use gamma value specified in
!                              SET_HET (Fisher et al., 2016).
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      LOGICAL  :: DO_EDUCT
      INTEGER  :: N
      REAL(fp) :: XSTKCF, ADJUSTEDRATE

      ! Initialize
      HET_ISOPND   = 0.0_fp
      ADJUSTEDRATE = 0.0_fp
      XSTKCF       = 0.0_fp

      ! Don't do PSC rate adjustment
      DO_EDUCT     = .FALSE.

      ! Loop over aerosol types
      DO N = 1, NAERO

         ! Define gamma
         IF (N.eq.8 .and. RELHUM >= CRITRH) THEN
            XSTKCF = B
         ENDIF

         IF (N.eq.13) THEN
            ! Calculate for stratospheric liquid aerosol
            ! Note that XSTKCF is actually a premultiplying
            ! factor in this case, including c-bar
            ADJUSTEDRATE = XAREA(N) * XSTKCF
         ELSE
            ! Reaction rate for surface of aerosol
            ADJUSTEDRATE=ARSL1K(XAREA(N),XRADI(N),XDENA,XSTKCF,XTEMP, &
                               (A**0.5_FP))
         ENDIF

         IF ( DO_EDUCT .and. N > 12 ) THEN
            ! PSC reaction - prevent excessive reaction rate
            IF (ADJUSTEDRATE.gt.(1.e+0_fp/HetMinLife)) THEN
               ADJUSTEDRATE = 1.e+0_fp/HetMinLife
            ENDIF
         ENDIF
         
         ! Add to overall reaction rate
         HET_ISOPND = HET_ISOPND + ADJUSTEDRATE
      END DO

    END FUNCTIOn HETISOPND
!EOC
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetISOPNB
!
! !DESCRIPTION: Sets the heterogenous chemistry rate for ISOPNB.
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETISOPNB( A, B ) RESULT( HET_ISOPNB )
!
! !INPUT PARAMETERS: 
!
      ! Rate coefficients
      REAL(fp), INTENT(IN) :: A, B
!
! !RETURN VALUE:
!
      REAL(fp)             :: HET_ISOPNB
!
! !REMARKS:
!
! !REVISION HISTORY:
!  15 Jun 2017 - M. Sulprizio- Initial version based on calcrate.F from E.Marais
!  14 Jul 2017 - M. Sulprizio- Product has been changed to IONITA, which also
!                              has heterogeneous reaction. Remove call to
!                              EPOXUPTK here and use gamma value specified in
!                              SET_HET (Fisher et al., 2016).
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      LOGICAL  :: DO_EDUCT
      INTEGER  :: N
      REAL(fp) :: XSTKCF, ADJUSTEDRATE

      ! Initialize
      HET_ISOPNB   = 0.0_fp
      ADJUSTEDRATE = 0.0_fp
      XSTKCF       = 0.0_fp

      ! Don't do PSC rate adjustment
      DO_EDUCT     = .FALSE.

      ! Loop over aerosol types
      DO N = 1, NAERO

         ! Define gamma
         IF (N.eq.8 .and. RELHUM >= CRITRH) THEN
            XSTKCF = B
         ENDIF

         IF (N.eq.13) THEN
            ! Calculate for stratospheric liquid aerosol
            ! Note that XSTKCF is actually a premultiplying
            ! factor in this case, including c-bar
            ADJUSTEDRATE = XAREA(N) * XSTKCF
         ELSE
            ! Reaction rate for surface of aerosol
            ADJUSTEDRATE=ARSL1K(XAREA(N),XRADI(N),XDENA,XSTKCF,XTEMP, &
                               (A**0.5_FP))
         ENDIF

         IF ( DO_EDUCT .and. N > 12 ) THEN
            ! PSC reaction - prevent excessive reaction rate
            IF (ADJUSTEDRATE.gt.(1.e+0_fp/HetMinLife)) THEN
               ADJUSTEDRATE = 1.e+0_fp/HetMinLife
            ENDIF
         ENDIF
         
         ! Add to overall reaction rate
         HET_ISOPNB = HET_ISOPNB + ADJUSTEDRATE
      END DO

    END FUNCTIOn HETISOPNB
!EOC
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetMACRN
!
! !DESCRIPTION: Sets the heterogenous chemistry rate for MACRN.
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETMACRN( A, B ) RESULT( HET_MACRN )
!
! !INPUT PARAMETERS: 
!
      ! Rate coefficients
      REAL(fp), INTENT(IN) :: A, B
!
! !RETURN VALUE:
!
      REAL(fp)             :: HET_MACRN
!
! !REMARKS:
!
! !REVISION HISTORY:
!  15 Jun 2017 - M. Sulprizio- Initial version based on calcrate.F from E.Marais
!  14 Jul 2017 - M. Sulprizio- Product has been changed to IONITA, which also
!                              has heterogeneous reaction. Remove call to
!                              EPOXUPTK here and use gamma value specified in
!                              SET_HET (Fisher et al., 2016).
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      LOGICAL  :: DO_EDUCT
      INTEGER  :: N
      REAL(fp) :: XSTKCF, ADJUSTEDRATE

      ! Initialize
      HET_MACRN    = 0.0_fp
      ADJUSTEDRATE = 0.0_fp
      XSTKCF       = 0.0_fp

      ! Don't do PSC rate adjustment
      DO_EDUCT     = .FALSE.

      ! Loop over aerosol types
      DO N = 1, NAERO

         ! Define gamma
         IF (N.eq.8 .and. RELHUM >= CRITRH) THEN
            XSTKCF = B
         ENDIF

         IF (N.eq.13) THEN
            ! Calculate for stratospheric liquid aerosol
            ! Note that XSTKCF is actually a premultiplying
            ! factor in this case, including c-bar
            ADJUSTEDRATE = XAREA(N) * XSTKCF
         ELSE
            ! Reaction rate for surface of aerosol
            ADJUSTEDRATE=ARSL1K(XAREA(N),XRADI(N),XDENA,XSTKCF,XTEMP, &
                               (A**0.5_FP))
         ENDIF

         IF ( DO_EDUCT .and. N > 12 ) THEN
            ! PSC reaction - prevent excessive reaction rate
            IF (ADJUSTEDRATE.gt.(1.e+0_fp/HetMinLife)) THEN
               ADJUSTEDRATE = 1.e+0_fp/HetMinLife
            ENDIF
         ENDIF
         
         ! Add to overall reaction rate
         HET_MACRN = HET_MACRN + ADJUSTEDRATE
      END DO

    END FUNCTIOn HETMACRN
!EOC
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetMVKN
!
! !DESCRIPTION: Sets the heterogenous chemistry rate for MVKN.
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETMVKN( A, B ) RESULT( HET_MVKN )
!
! !INPUT PARAMETERS: 
!
      ! Rate coefficients
      REAL(fp), INTENT(IN) :: A, B
!
! !RETURN VALUE:
!
      REAL(fp)             :: HET_MVKN
!
! !REMARKS:
!
! !REVISION HISTORY:
!  15 Jun 2017 - M. Sulprizio- Initial version based on calcrate.F from E.Marais
!  14 Jul 2017 - M. Sulprizio- Product has been changed to IONITA, which also
!                              has heterogeneous reaction. Remove call to
!                              EPOXUPTK here and use gamma value specified in
!                              SET_HET (Fisher et al., 2016).
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      LOGICAL  :: DO_EDUCT
      INTEGER  :: N
      REAL(fp) :: XSTKCF, ADJUSTEDRATE

      ! Initialize
      HET_MVKN     = 0.0_fp
      ADJUSTEDRATE = 0.0_fp
      XSTKCF       = 0.0_fp

      ! Don't do PSC rate adjustment
      DO_EDUCT     = .FALSE.

      ! Loop over aerosol types
      DO N = 1, NAERO

         ! Define gamma
         IF (N.eq.8 .and. RELHUM >= CRITRH) THEN
            XSTKCF = B
         ENDIF

         IF (N.eq.13) THEN
            ! Calculate for stratospheric liquid aerosol
            ! Note that XSTKCF is actually a premultiplying
            ! factor in this case, including c-bar
            ADJUSTEDRATE = XAREA(N) * XSTKCF
         ELSE
            ! Reaction rate for surface of aerosol
            ADJUSTEDRATE=ARSL1K(XAREA(N),XRADI(N),XDENA,XSTKCF,XTEMP, &
                               (A**0.5_FP))
         ENDIF

         IF ( DO_EDUCT .and. N > 12 ) THEN
            ! PSC reaction - prevent excessive reaction rate
            IF (ADJUSTEDRATE.gt.(1.e+0_fp/HetMinLife)) THEN
               ADJUSTEDRATE = 1.e+0_fp/HetMinLife
            ENDIF
         ENDIF
         
         ! Add to overall reaction rate
         HET_MVKN = HET_MVKN + ADJUSTEDRATE
      END DO

    END FUNCTIOn HETMVKN
!EOC
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetR4N2
!
! !DESCRIPTION: Sets the heterogenous chemistry rate for R4N2.
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETR4N2( A, B ) RESULT( HET_R4N2 )
!
! !INPUT PARAMETERS: 
!
      ! Rate coefficients
      REAL(fp), INTENT(IN) :: A, B
!
! !RETURN VALUE:
!
      REAL(fp)             :: HET_R4N2
!
! !REMARKS:
!
! !REVISION HISTORY:
!  15 Jun 2017 - M. Sulprizio- Initial version based on calcrate.F from E.Marais
!  14 Jul 2017 - M. Sulprizio- Product has been changed to IONITA, which also
!                              has heterogeneous reaction. Remove call to
!                              EPOXUPTK here and use gamma value specified in
!                              SET_HET (Fisher et al., 2016).
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      LOGICAL  :: DO_EDUCT
      INTEGER  :: N
      REAL(fp) :: XSTKCF, ADJUSTEDRATE

      ! Initialize
      HET_R4N2   = 0.0_fp
      ADJUSTEDRATE = 0.0_fp
      XSTKCF       = 0.0_fp

      ! Don't do PSC rate adjustment
      DO_EDUCT     = .FALSE.

      ! Loop over aerosol types
      DO N = 1, NAERO

         ! Define gamma
         IF (N.eq.8 .and. RELHUM >= CRITRH) THEN
            XSTKCF = B
         ENDIF

         IF (N.eq.13) THEN
            ! Calculate for stratospheric liquid aerosol
            ! Note that XSTKCF is actually a premultiplying
            ! factor in this case, including c-bar
            ADJUSTEDRATE = XAREA(N) * XSTKCF
         ELSE
            ! Reaction rate for surface of aerosol
            ADJUSTEDRATE=ARSL1K(XAREA(N),XRADI(N),XDENA,XSTKCF,XTEMP, &
                               (A**0.5_FP))
         ENDIF

         IF ( DO_EDUCT .and. N > 12 ) THEN
            ! PSC reaction - prevent excessive reaction rate
            IF (ADJUSTEDRATE.gt.(1.e+0_fp/HetMinLife)) THEN
               ADJUSTEDRATE = 1.e+0_fp/HetMinLife
            ENDIF
         ENDIF
         
         ! Add to overall reaction rate
         HET_R4N2 = HET_R4N2 + ADJUSTEDRATE
      END DO

    END FUNCTIOn HETR4N2
!EOC
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetDHDN
!
! !DESCRIPTION: Sets the heterogenous chemistry rate for DHDN.
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETDHDN( A, B ) RESULT( HET_DHDN )
!
! !INPUT PARAMETERS: 
!
      ! Rate coefficients
      REAL(fp), INTENT(IN) :: A, B
!
! !RETURN VALUE:
!
      REAL(fp)             :: HET_DHDN
!
! !REMARKS:
!
! !REVISION HISTORY:
!  15 Jun 2017 - M. Sulprizio- Initial version based on calcrate.F from E.Marais
!  14 Jul 2017 - M. Sulprizio- Product has been changed to IONITA, which also
!                              has heterogeneous reaction. Remove call to
!                              EPOXUPTK here and use gamma value specified in
!                              SET_HET (Fisher et al., 2016).
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      LOGICAL  :: DO_EDUCT
      INTEGER  :: N
      REAL(fp) :: XSTKCF, ADJUSTEDRATE

      ! Initialize
      HET_DHDN     = 0.0_fp
      ADJUSTEDRATE = 0.0_fp
      XSTKCF       = 0.0_fp

      ! Don't do PSC rate adjustment
      DO_EDUCT     = .FALSE.

      ! Loop over aerosol types
      DO N = 1, NAERO

         ! Define gamma
         IF (N.eq.8 .and. RELHUM >= CRITRH) THEN
            XSTKCF = B
         ENDIF

         IF (N.eq.13) THEN
            ! Calculate for stratospheric liquid aerosol
            ! Note that XSTKCF is actually a premultiplying
            ! factor in this case, including c-bar
            ADJUSTEDRATE = XAREA(N) * XSTKCF
         ELSE
            ! Reaction rate for surface of aerosol
            ADJUSTEDRATE=ARSL1K(XAREA(N),XRADI(N),XDENA,XSTKCF,XTEMP, &
                               (A**0.5_FP))
         ENDIF

         IF ( DO_EDUCT .and. N > 12 ) THEN
            ! PSC reaction - prevent excessive reaction rate
            IF (ADJUSTEDRATE.gt.(1.e+0_fp/HetMinLife)) THEN
               ADJUSTEDRATE = 1.e+0_fp/HetMinLife
            ENDIF
         ENDIF
         
         ! Add to overall reaction rate
         HET_DHDN = HET_DHDN + ADJUSTEDRATE
      END DO

    END FUNCTIOn HETDHDN
!EOC
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetMONITS
!
! !DESCRIPTION: Sets the heterogenous chemistry rate for MONITS
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETMONITS( A, B ) RESULT( HET_MONITS )
!
! !INPUT PARAMETERS: 
!
      ! Rate coefficients
      REAL(fp), INTENT(IN) :: A, B
!
! !RETURN VALUE:
!
      REAL(fp)             :: HET_MONITS
!
! !REMARKS:
!
! !REVISION HISTORY:
!  14 Jul 2017 - M. Sulprizio- Initial version based on SEAC4RS code and Fisher
!                              et al. 2016.
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      LOGICAL  :: DO_EDUCT
      INTEGER  :: N
      REAL(fp) :: XSTKCF, ADJUSTEDRATE

      ! Initialize
      HET_MONITS   = 0.0_fp
      ADJUSTEDRATE = 0.0_fp
      XSTKCF       = 0.0_fp

      ! Don't do PSC rate adjustment
      DO_EDUCT     = .FALSE.

      ! Loop over aerosol types
      DO N = 1, NAERO

         ! Define gamma
         IF (N.eq.8 .and. RELHUM >= CRITRH) THEN
            XSTKCF = B
         ENDIF

         IF (N.eq.13) THEN
            ! Calculate for stratospheric liquid aerosol
            ! Note that XSTKCF is actually a premultiplying
            ! factor in this case, including c-bar
            ADJUSTEDRATE = XAREA(N) * XSTKCF
         ELSE
            ! Reaction rate for surface of aerosol
            ADJUSTEDRATE=ARSL1K(XAREA(N),XRADI(N),XDENA,XSTKCF,XTEMP, &
                               (A**0.5_FP))
         ENDIF

         IF ( DO_EDUCT .and. N > 12 ) THEN
            ! PSC reaction - prevent excessive reaction rate
            IF (ADJUSTEDRATE.gt.(1.e+0_fp/HetMinLife)) THEN
               ADJUSTEDRATE = 1.e+0_fp/HetMinLife
            ENDIF
         ENDIF
         
         ! Add to overall reaction rate
         HET_MONITS = HET_MONITS + ADJUSTEDRATE
      END DO

    END FUNCTIOn HETMONITS
!EOC
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetMONITU
!
! !DESCRIPTION: Sets the heterogenous chemistry rate for MONITU
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETMONITU( A, B ) RESULT( HET_MONITU )
!
! !INPUT PARAMETERS: 
!
      ! Rate coefficients
      REAL(fp), INTENT(IN) :: A, B
!
! !RETURN VALUE:
!
      REAL(fp)             :: HET_MONITU
!
! !REMARKS:
!
! !REVISION HISTORY:
!  14 Jul 2017 - M. Sulprizio- Initial version based on SEAC4RS code and Fisher
!                              et al. 2016.
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      LOGICAL  :: DO_EDUCT
      INTEGER  :: N
      REAL(fp) :: XSTKCF, ADJUSTEDRATE

      ! Initialize
      HET_MONITU   = 0.0_fp
      ADJUSTEDRATE = 0.0_fp
      XSTKCF       = 0.0_fp

      ! Don't do PSC rate adjustment
      DO_EDUCT     = .FALSE.

      ! Loop over aerosol types
      DO N = 1, NAERO

         ! Define gamma
         IF (N.eq.8 .and. RELHUM >= CRITRH) THEN
            XSTKCF = B
         ENDIF

         IF (N.eq.13) THEN
            ! Calculate for stratospheric liquid aerosol
            ! Note that XSTKCF is actually a premultiplying
            ! factor in this case, including c-bar
            ADJUSTEDRATE = XAREA(N) * XSTKCF
         ELSE
            ! Reaction rate for surface of aerosol
            ADJUSTEDRATE=ARSL1K(XAREA(N),XRADI(N),XDENA,XSTKCF,XTEMP, &
                               (A**0.5_FP))
         ENDIF

         IF ( DO_EDUCT .and. N > 12 ) THEN
            ! PSC reaction - prevent excessive reaction rate
            IF (ADJUSTEDRATE.gt.(1.e+0_fp/HetMinLife)) THEN
               ADJUSTEDRATE = 1.e+0_fp/HetMinLife
            ENDIF
         ENDIF
         
         ! Add to overall reaction rate
         HET_MONITU = HET_MONITU + ADJUSTEDRATE
      END DO

    END FUNCTIOn HETMONITU
!EOC
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetHONIT
!
! !DESCRIPTION: Sets the heterogenous chemistry rate for HONIT
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETHONIT( A, B ) RESULT( HET_HONIT )
!
! !INPUT PARAMETERS: 
!
      ! Rate coefficients
      REAL(fp), INTENT(IN) :: A, B
!
! !RETURN VALUE:
!
      REAL(fp)             :: HET_HONIT
!
! !REMARKS:
!
! !REVISION HISTORY:
!  14 Jul 2017 - M. Sulprizio- Initial version based on SEAC4RS code and Fisher
!                              et al. 2016.
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      LOGICAL  :: DO_EDUCT
      INTEGER  :: N
      REAL(fp) :: XSTKCF, ADJUSTEDRATE

      ! Initialize
      HET_HONIT    = 0.0_fp
      ADJUSTEDRATE = 0.0_fp
      XSTKCF       = 0.0_fp

      ! Don't do PSC rate adjustment
      DO_EDUCT     = .FALSE.

      ! Loop over aerosol types
      DO N = 1, NAERO

         ! Define gamma
         IF (N.eq.8 .and. RELHUM >= CRITRH) THEN
            XSTKCF = B
         ENDIF

         IF (N.eq.13) THEN
            ! Calculate for stratospheric liquid aerosol
            ! Note that XSTKCF is actually a premultiplying
            ! factor in this case, including c-bar
            ADJUSTEDRATE = XAREA(N) * XSTKCF
         ELSE
            ! Reaction rate for surface of aerosol
            ADJUSTEDRATE=ARSL1K(XAREA(N),XRADI(N),XDENA,XSTKCF,XTEMP, &
                               (A**0.5_FP))
         ENDIF

         IF ( DO_EDUCT .and. N > 12 ) THEN
            ! PSC reaction - prevent excessive reaction rate
            IF (ADJUSTEDRATE.gt.(1.e+0_fp/HetMinLife)) THEN
               ADJUSTEDRATE = 1.e+0_fp/HetMinLife
            ENDIF
         ENDIF
         
         ! Add to overall reaction rate
         HET_HONIT = HET_HONIT + ADJUSTEDRATE
      END DO

    END FUNCTIOn HETHONIT
!EOC
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetIONITA
!
! !DESCRIPTION: Sets the heterogenous chemistry rate for IONITA: Aerosol-phase
!  organic nitrate formed from monoterpene precursors.
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETIONITA( A, B ) RESULT( HET_IONITA )
!
! !INPUT PARAMETERS: 
!
      ! Rate coefficients
      REAL(fp), INTENT(IN) :: A, B
!
! !RETURN VALUE:
!
      REAL(fp)             :: HET_IONITA
!
! !REMARKS:
!
! !REVISION HISTORY:
!  14 Jul 2017 - M. Sulprizio- Initial version based on SEAC4RS code and Fisher
!                              et al. 2016.
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      LOGICAL  :: DO_EDUCT
      INTEGER  :: N
      REAL(fp) :: XSTKCF, ADJUSTEDRATE

      ! Initialize
      HET_IONITA   = 0.0_fp
      ADJUSTEDRATE = 0.0_fp
      XSTKCF       = 0.0_fp

      ! Don't do PSC rate adjustment
      DO_EDUCT     = .FALSE.

      ! Loop over aerosol types
      DO N = 1, NAERO

         ! Define gamma for IONITA 
         ! Imposed lifetime = 1 hour (Fisher et al., 2016)
         XSTKCF = 2.78e-4_fp

         IF (N.eq.13) THEN
            ! Calculate for stratospheric liquid aerosol
            ! Note that XSTKCF is actually a premultiplying
            ! factor in this case, including c-bar
            ADJUSTEDRATE = XAREA(N) * XSTKCF
         ELSE
            ! Reaction rate for surface of aerosol
            ADJUSTEDRATE=ARSL1K(XAREA(N),XRADI(N),XDENA,XSTKCF,XTEMP, &
                               (A**0.5_FP))
         ENDIF

         IF ( DO_EDUCT .and. N > 12 ) THEN
            ! PSC reaction - prevent excessive reaction rate
            IF (ADJUSTEDRATE.gt.(1.e+0_fp/HetMinLife)) THEN
               ADJUSTEDRATE = 1.e+0_fp/HetMinLife
            ENDIF
         ENDIF
         
         ! Add to overall reaction rate
         !HET_IONITA = HET_IONITA + ADJUSTEDRATE

      END DO
      HET_IONITA = 2.78e-4_fp

    END FUNCTIOn HETIONITA
!EOC
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetMONITA
!
! !DESCRIPTION: Sets the heterogenous chemistry rate for MONITA: Aerosol-phase
!  organic nitrate formed from monoterpene precursors.
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETMONITA( A, B ) RESULT( HET_MONITA )
!
! !INPUT PARAMETERS: 
!
      ! Rate coefficients
      REAL(fp), INTENT(IN) :: A, B
!
! !RETURN VALUE:
!
      REAL(fp)             :: HET_MONITA
!
! !REMARKS:
!
! !REVISION HISTORY:
!  14 Jul 2017 - M. Sulprizio- Initial version based on SEAC4RS code and Fisher
!                              et al. 2016.
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      LOGICAL  :: DO_EDUCT
      INTEGER  :: N
      REAL(fp) :: XSTKCF, ADJUSTEDRATE

      ! Initialize
      HET_MONITA   = 0.0_fp
      ADJUSTEDRATE = 0.0_fp
      XSTKCF       = 0.0_fp

      ! Don't do PSC rate adjustment
      DO_EDUCT     = .FALSE.

      ! Loop over aerosol types
      DO N = 1, NAERO

         ! Define gamma for MONITA 
         ! Imposed lifetime = 1 hour (Fisher et al., 2016)
         XSTKCF = 2.78e-4_fp

         IF (N.eq.13) THEN
            ! Calculate for stratospheric liquid aerosol
            ! Note that XSTKCF is actually a premultiplying
            ! factor in this case, including c-bar
            ADJUSTEDRATE = XAREA(N) * XSTKCF
         ELSE
            ! Reaction rate for surface of aerosol
            ADJUSTEDRATE=ARSL1K(XAREA(N),XRADI(N),XDENA,XSTKCF,XTEMP, &
                               (A**0.5_FP))
         ENDIF

         IF ( DO_EDUCT .and. N > 12 ) THEN
            ! PSC reaction - prevent excessive reaction rate
            IF (ADJUSTEDRATE.gt.(1.e+0_fp/HetMinLife)) THEN
               ADJUSTEDRATE = 1.e+0_fp/HetMinLife
            ENDIF
         ENDIF
         
         ! Add to overall reaction rate
         !HET_MONITA = HET_MONITA + ADJUSTEDRATE
      END DO

      HET_MONITA = 2.78e-4_fp

    END FUNCTIOn HETMONITA
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetOH
!
! !DESCRIPTION: Set heterogenous chemistry rate for N2O5 with Cl-. 
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETOH(denAir, rAer, AAer, TK, C_X) RESULT( kISum )
!
! !INPUT PARAMETERS:
!
      REAL(fp), INTENT(IN) :: denAir      ! Density of air (#/cm3)
      REAL(fp), INTENT(IN) :: rAer        ! Radius of aerosol (cm)
      REAL(fp), INTENT(IN) :: AAer        ! Area of aerosol (cm2/cm3)
      REAL(fp), INTENT(IN) :: TK          ! Temperature (K)
      REAL(fp), INTENT(IN) :: C_X         ! Cl- concentration (mol/L)
!
! !RETURN VALUE:
!
      REAL(fp)             :: kISum
!
! !REMARKS:
!
! !REVISION HISTORY:
!  12 Mar 2018 - X. Wang  - Initial version
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      INTEGER  :: N
      REAL(fp) :: XSTKCF
      Real(fp), Parameter :: XMolWeight=17.0e+0_fp
      Real(fp), Parameter :: XSQM=SQRT(XMolWeight)
!
! !DEFINED PARAMETERS:
!
      ! Initialize
      kISum        = 0.0_fp
      XSTKCF       = 0.0_fp

      XSTKCF = 0.04_fp * C_X   !Knipping and Dabdub (2002)

      ! Reaction rate
      kISum = ARSL1K( AAer, rAer, denAir, XSTKCF, XTEMP, XSQM )

    END FUNCTION HETOH
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetN2O5_SS
!
! !DESCRIPTION: Set heterogenous chemistry rate for N2O5 on sea salt. This
!  reaction follows the N2O5 + Cl- channel, and Cl- is assumed to be in excess.
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETN2O5_SS(denAir, rAer, AAer, TK, C_X, X) RESULT( kISum )
!
! !INPUT PARAMETERS: 
!
      REAL(fp), INTENT(IN) :: denAir      ! Density of air (#/cm3)
      REAL(fp), INTENT(IN) :: rAer        ! Radius of aerosol (cm)
      REAL(fp), INTENT(IN) :: AAer        ! Area of aerosol (cm2/cm3)
      REAL(fp), INTENT(IN) :: TK          ! Temperature (K)
      REAL(fp), INTENT(IN) :: C_X         ! Cl- concentration (mol/L)
      INTEGER,  INTENT(IN) :: X           ! X = 1 fine; 2 coarse
!
! !RETURN VALUE:
!
      REAL(fp)             :: kISum
!
! !REMARKS:
!
! !REVISION HISTORY:
!  29 Mar 2016 - R. Yantosca - Added ProTeX header
!  01 Apr 2016 - R. Yantosca - Define N, XSTKCF, ADJUSTEDRATE locally
!  01 Apr 2016 - R. Yantosca - Replace KII_KI with DO_EDUCT local variable
!  15 Jan 2018 - X. Wang     - Updated function for Cl-(p) simulation
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      INTEGER  :: N
      REAL(fp) :: XSTKCF
      REAL(fp) :: GAM_N2O5, r_gp
      Real(fp), Parameter :: XMolWeight=108.0e+0_fp
      Real(fp), Parameter :: XSQM=SQRT(XMolWeight)
!
! !DEFINED PARAMETERS:
!
      ! Initialize
      kISum        = 0.0_fp
      XSTKCF       = 0.0_fp
      GAM_N2O5     = 0.0_fp
      r_gp         = 1.0_fp

      ! Directly calculate for sea salt and NH4Cl only
      ! Get GAMMA for N2O5 hydrolysis, which is
      ! a function of aerosol type, temp, and RH

      ! Sea salt - follows the N2O5 + Cl- channel
      CALL GAMMA_N2O5_Cl(C_X, RELHUM, X, Gam_N2O5, r_gp)
      XSTKCF = Gam_N2O5

      ! Reaction rate
      kISum = ARSL1K( AAer, rAer, denAir, XSTKCF, XTEMP, XSQM )*r_gp
  
    END FUNCTION HETN2O5_SS
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetN2O5_HCl
!
! !DESCRIPTION: Set heterogenous chemistry rate for N2O5(g) + HCl(l,s)
!  in polar stratospheric clouds and on tropospheric sulfate aerosol.
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETN2O5_HCl( A, B ) RESULT( kISum )
!
! !INPUT PARAMETERS: 
!
      ! Rate coefficients
      REAL(fp), INTENT(IN) :: A, B
!
! !RETURN VALUE:
!
      REAL(fp)             :: kISum
!
! !REMARKS:
!  This routine is only activated for UCX-based mechanisms.
!
! !REVISION HISTORY:
!  29 Jan 2016 - M. Sulprizio- Initial version, adapted from code previously
!                              in calcrate.F
!  29 Mar 2016 - R. Yantosca - Added ProTeX header
!  01 Apr 2016 - R. Yantosca - Define N, XSTKCF, ADJUSTEDRATE locally
!  01 Apr 2016 - R. Yantosca - Replace KII_KI with DO_EDUCT local variable
!  04 May 2016 - M. Sulprizio- Add fixes for setting rate if not a STRATBOX
!  24 Dec 2016 - S. D. Eastham - Extended into the troposphere. Also now use the
!                              standard N2O5 calculation to establish gamma for
!                              sulfate, rather than relying on a fixed factor.
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      INTEGER  :: N
      REAL(fp) :: XSTKCF, ADJUSTEDRATE

      ! Initialize
      kISum        = 0.0_fp
      ADJUSTEDRATE = 0.0_fp
      XSTKCF       = 0.0_fp

      ! Loop over aerosol types
      DO N = 1, NAERO

         ! Assume zero
         XStkCf = 0.0e+0_fp
	 ! restore stratosphere only limitation - tms 17/04/10
         IF ( STRATBOX ) THEN
            IF (N.eq.8) THEN
               ! Fixed gamma?
               !XSTKCF = 0.1e-4_fp ! Sulfate
               ! RH dependence
      	       XSTKCF = N2O5( N, TEMPK, RELHUM )
	    ENDIF
          ENDIF
#if defined( UCX )
         ! Only consider PSC reactions in strat
         IF ( STRATBOX ) THEN
            IF (N.eq.13) THEN
               XSTKCF = KHETI_SLA(2)
            ELSEIF (N.eq.14) THEN
               IF (NATSURFACE) THEN
                  XSTKCF = 0.003e+0_fp ! NAT
               ELSE
                  XSTKCF = 0.03e+0_fp ! Ice
               ENDIF
            ENDIF
         ENDIF
#endif

         IF (XStkCf.gt.0.0e+0_fp) THEN
            IF (N.eq.13) THEN
               ! Calculate for stratospheric liquid aerosol
               ! Note that XSTKCF is actually a premultiplying
               ! factor in this case, including c-bar
               ADJUSTEDRATE = XAREA(N) * XSTKCF
            ELSE
               ! Reaction rate for surface of aerosol
               ADJUSTEDRATE=ARSL1K(XAREA(N),XRADI(N),XDENA,XSTKCF,XTEMP, &
                                  (A**0.5_FP))
            ENDIF
   
            ! Add to overall reaction rate
            kISum = kISum + ADJUSTEDRATE
         ENDIF

      END DO

    END FUNCTION HETN2O5_HCl
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetHXUptake_js
!
! !DESCRIPTION: Sets the uptake rate of HCl and HBr on sea salt using Johan
!  Schmidt's updated code.
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETHXUptake_JS( denAir, rAer, AAer, TK, X ) RESULT( kISum )
!
! !INPUT PARAMETERS: 
!
      REAL(fp), INTENT(IN) :: denAir      ! Density of air (#/cm3)
      REAL(fp), INTENT(IN) :: rAer        ! Radius of aerosol (cm)
      REAL(fp), INTENT(IN) :: AAer        ! Area of aerosol (cm2/cm3)
      REAL(fp), INTENT(IN) :: TK          ! Temperature (K)
      INTEGER,  INTENT(IN) :: X           ! 1: Cl-, 2: Br-
!
! !RETURN VALUE:
!
      REAL(fp)             :: kISum
!
! !REMARKS:
!
! !REVISION HISTORY:
!  29 Mar 2016 - R. Yantosca - Added ProTeX header
!  01 Apr 2016 - R. Yantosca - Define N, XSTKCF, ADJUSTEDRATE locally
!  01 Apr 2016 - R. Yantosca - Replace KII_KI with DO_EDUCT local variable
!  22 Dec 2016 - S. D. Eastham - Updated code based on Johan Schmidt's work
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      INTEGER  :: N
      REAL(fp) :: XSTKCF, ADJUSTEDRATE, XSqM
      Real(fp), Parameter :: XMolWeightHCl=36.5e+0_fp
      Real(fp), Parameter :: XSqMHCl=SQRT(XMolWeightHCl)
      Real(fp), Parameter :: XMolWeightHBr=81.0e+0_fp
      Real(fp), Parameter :: XSqMHBr=SQRT(XMolWeightHBr)

      ! Initialize
      kISum        = 0.0_fp

      ! Select between halogens
      IF (X.eq.1) THEN
         ! This would never be used since HCl uptake is 
         ! handled by ISSOROPIA now, xnw 1/25/18
         XSqM = XSqMHCl
      ELSEIF (X.eq.2) THEN
         XSqM = XSqMHBr
      ENDIF
       
      XStkCf = Gamma_HX_Uptake( rAer, denAir, X, TK )

      ! Reaction rate for surface of aerosol
      kISum = Arsl1K(AAer,rAer,denAir,XStkCf,XTemp,XSqM)

    END FUNCTION HETHXUptake_JS
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetO3_SS_JS
!
! !DESCRIPTION: Sets the O3 + Br- (in sea salt) rate using Johan
!  Schmidt's updated code.
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETO3_SS_JS( denAir, rAer, AAer, alkAer, TK, halConc, O3Conc ) &
                             RESULT( kISum )
!
! !INPUT PARAMETERS: 
!
      REAL(fp), INTENT(IN) :: denAir      ! Density of air (#/cm3)
      REAL(fp), INTENT(IN) :: rAer        ! Radius of aerosol (cm)
      REAL(fp), INTENT(IN) :: AAer        ! Area of aerosol (cm2/cm3)
      REAL(fp), INTENT(IN) :: alkAer      ! Aerosol alkalinity (?)
      REAL(fp), INTENT(IN) :: TK          ! Temperature (K)
      REAL(fp), INTENT(IN) :: halConc     ! Halide concentration (mol/L)
      REAL(fp), INTENT(IN) :: O3Conc      ! Ozone concentration (#/cm3)
!
! !RETURN VALUE:
!
      REAL(fp)             :: kISum
!
! !REMARKS:
!
! !REVISION HISTORY:
!  29 Mar 2016 - R. Yantosca - Added ProTeX header
!  01 Apr 2016 - R. Yantosca - Define N, XSTKCF, ADJUSTEDRATE locally
!  01 Apr 2016 - R. Yantosca - Replace KII_KI with DO_EDUCT local variable
!  22 Dec 2016 - S. D. Eastham - Updated code based on Johan Schmidt's work
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      INTEGER  :: N
      REAL(fp) :: XSTKCF, ADJUSTEDRATE
      Real(fp), Parameter :: XMolWeight=48.0e+0_fp
      Real(fp), Parameter :: XSQM=SQRT(XMolWeight)

      ! Initialize
      kISum        = 0.0_fp

      ! Reaction can only proceed on acidic aerosol
      IF (alkAer > 0.05e+0_fp) THEN
         XStkCf = 0.0e+0_fp
      ELSE
         XStkCf = Gamma_O3_Br( rAer, denAir, TK, halConc, O3Conc )
      ENDIF

      ! Reaction rate for surface of aerosol
      kISum = Arsl1K(AAer,rAer,denAir,XStkCf,XTemp,XSqM) 

    END FUNCTION HETO3_SS_JS
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetNO3_Cl
!
! !DESCRIPTION: Sets the NO3(g) hypsis rate on Cl-.
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETNO3_Cl( denAir, rAer, AAer, TK, clConc) &
                             RESULT( kISum )
!
! !INPUT PARAMETERS:
!
      REAL(fp), INTENT(IN) :: denAir      ! Density of air (#/cm3)
      REAL(fp), INTENT(IN) :: rAer        ! Radius of aerosol (cm)
      REAL(fp), INTENT(IN) :: AAer        ! Area of aerosol (cm2/cm3)
      REAL(fp), INTENT(IN) :: TK          ! Temperature (K)
      REAL(fp), INTENT(IN) :: clConc      ! Cloride concentration (mol/L)
!
! !RETURN VALUE:
!
      REAL(fp)             :: kISum
!
! !REMARKS:
!
! !REVISION HISTORY:
!  14 Mar 2018 - X. Wang - Initial version
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      REAL(fp) :: XSTKCF
      Real(fp), Parameter :: XMolWeight=62.0e+0_fp
      Real(fp), Parameter :: XSQM=SQRT(XMolWeight)

      ! Initialize
      kISum        = 0.0_fp

      ! Reaction can only proceed on acidic aerosol
      XStkCf = GAMMA_NO3(rAer, TK, clConc)

      ! Reaction rate for surface of aerosol
      kISum = Arsl1K(AAer,rAer,denAir,XStkCf,XTemp,XSqM)

    END FUNCTION HETNO3_Cl
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetClNO2_TCld
!
! !DESCRIPTION: Sets the rate of the multiphase reaction ClNO2 + Cl-/Br- in
!  troposphere cloud
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETClNO2_TCld( denAir, rLiq, rIce, ALiq, AIce, VAir, TK, &
                           pH, clConc_A, clConc_C, clConc_g,&
                           brConc_A, brConc_C, brConc_g, X) &
                           RESULT( kISum )
!
! !INPUT PARAMETERS:
!
      REAL(fp), INTENT(IN) :: denAir      ! Density of air (#/cm3)
      REAL(fp), INTENT(IN) :: rLiq        ! Radius of liquid cloud droplets (cm)
      REAL(fp), INTENT(IN) :: rIce        ! Radius of ice cloud crystals (cm)
      REAL(fp), INTENT(IN) :: ALiq        ! Area of liquid cloud droplets (cm2/cm3)
      REAL(fp), INTENT(IN) :: AIce        ! Area of ice cloud crystals (cm2/cm3)
      REAL(fp), INTENT(IN) :: VAir        ! Box volume (cm3)
      REAL(fp), INTENT(IN) :: TK          ! Temperature (K)
      REAL(fp), INTENT(IN) :: clConc_A    ! Fine Chloride concentration (mol/L)
      REAL(fp), INTENT(IN) :: clConc_C    ! Coarse Chloride concentration (mol/L)
      REAL(fp), INTENT(IN) :: clConc_g
      REAL(fp), INTENT(IN) :: brConc_A    ! Fine Bromide concentration (mol/L)
      REAL(fp), INTENT(IN) :: brConc_C    ! Coarse Bromide concentration (mol/L)
      REAL(fp), INTENT(IN) :: brConc_g
      REAL(fp), INTENT(IN) :: pH
      INTEGER,  INTENT(IN) :: X           ! 1=fineCl;2=coarseCl;3=HCl,4=fineBr;5=coarseBr;6=HBr
!
! !RETURN VALUE:
!
      REAL(fp)             :: kISum
!
 !REMARKS:
!
! !REVISION HISTORY:
!  08 Aug 2018 - X. Wang      - Initial version
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      REAL(fp) :: XSTKCF, ADJUSTEDRATE
      Real(fp), Parameter :: XMolWeight=81.45e+0_fp
      Real(fp), Parameter :: XSQM=SQRT(XMolWeight)
      REAL(fp) :: GAM_ClNO2, r_gp, clConc, r_ac, brConc
      Integer  :: Y

      ! Initialize
      kISum        = 0.0_fp
      ADJUSTEDRATE = 0.0_fp
      XSTKCF       = 0.0_fp

      ! Cloud halide concentration, put fine and coarse mode together
      clConc = clConc_A + clConc_C + clConc_g
      brConc = brConc_A + brConc_C + brConc_g

      If (X == 1) THEN
         r_ac = clConc_A / clConc
         Y = 1
      ELSEIF (X == 2) THEN
         r_ac = clConc_C / clConc
         Y = 1
      ElSEIF (X == 3) THEN
         r_ac = clConc_g / clConc
         Y = 1
      ELSEIF (X == 4) THEN
         r_ac = brConc_A / brConc
         Y = 2
      ELSEIF (X == 5) THEN
         r_ac = brConc_C / brConc
         Y = 2
      ELSEIF (X == 6) THEN
         r_ac = brConc_g / brConc
         Y = 2
      ENDIF

      IF (.not. StratBox) THEN
       IF (ALiq.gt.0.0e+0_fp) THEN
          CALL GAMMA_ClNO2(rLiq, denAir, TK, pH, clConc, brConc, Y, &
                               GAM_ClNO2, r_gp)
          XSTKCF = GAM_ClNO2
          kISum = kISum + Arsl1K(ALiq, rLiq, denAir, XStkCf, XTemp, XSqM)*r_gp*r_ac
       ENDIF
       IF (AIce.gt.0.0e+0_fp) THEN
          CALL GAMMA_ClNO2(rIce, denAir, TK, pH, clConc, brConc, Y, &
                               GAM_ClNO2, r_gp)
          XSTKCF = GAM_ClNO2
          kISum = kISum + Arsl1K(AIce, rIce, denAir, XStkCf, XTemp, XSqM)*r_gp*r_ac
       ENDIF
      ENDIF

    END FUNCTION HetClNO2_TCld
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetClNO2
!
! !DESCRIPTION: Sets the ClNO2 + Cl- (in fine mode) rate.
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETClNO2( denAir, rAer, AAer, alkAer, TK, pH, clConc, brConc,X) &
                             RESULT( kISum )
!
! !INPUT PARAMETERS:
!
      REAL(fp), INTENT(IN) :: denAir      ! Density of air (#/cm3)
      REAL(fp), INTENT(IN) :: rAer        ! Radius of aerosol (cm)
      REAL(fp), INTENT(IN) :: AAer        ! Area of aerosol (cm2/cm3)
      REAL(fp), INTENT(IN) :: alkAer      ! Aerosol alkalinity (?)
      REAL(fp), INTENT(IN) :: TK          ! Temperature (K)
      REAL(fp), INTENT(IN) :: clConc      ! Cloride concentration (mol/L)
      REAL(fp), INTENT(IN) :: brConc      ! Bromide concentration (mol/L)
      REAL(fp), INTENT(IN) :: pH          ! Aerosol pH
      Integer,  INTENT(IN) :: X           ! 1: Cl-, 2: Br-
!
! !RETURN VALUE:
!
      REAL(fp)             :: kISum
!
! !REMARKS:
!
! !REVISION HISTORY:
!  14 Mar 2018 - X. Wang - Initial version
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      REAL(fp) :: XSTKCF
      Real(fp), Parameter :: XMolWeight=81.45e+0_fp
      Real(fp), Parameter :: XSQM=SQRT(XMolWeight)
      REAL(fp) :: GAM_ClNO2, r_gp
      

      ! Initialize
      kISum        = 0.0_fp
      GAM_ClNO2    = 0.0_fp
      r_gp         = 0.0_fp

      CALL GAMMA_ClNO2(rAer, denAir, TK, pH, clConc, brConc, X, GAM_ClNO2, r_gp)
      XStkCf = GAM_ClNO2


      ! Reaction rate for surface of aerosol
      kISum = Arsl1K(AAer,rAer,denAir,XStkCf,XTemp,XSqM) * r_gp

    END FUNCTION HETClNO2
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: Gamma_NO3
!
! !DESCRIPTION: Function GAMMA\_NO3 calculates reactive uptake coef.
!               for NO3 on salts
!\\
!\\
! !INTERFACE:
!
    FUNCTION GAMMA_NO3(Radius, T, C_X) RESULT(GAM_NO3)
!
! !USES:
!
      USE PhysConstants,      ONLY : Pi, RStarG
!
! !OUTPUT PARAMETER:
      ! Reactive uptake coefficient (unitless)
      REAL(fp)                       :: GAM_NO3
! !INPUT PARAMETERS:
!
      REAL(fp), INTENT(IN)           :: Radius
      REAL(fp), INTENT(IN)           :: T        ! Temperature (K)
      REAL(fp), INTENT(IN)           :: C_X      ! Cl- Concentration (mol/L)
!
! !REVISION HISTORY:
!  16 Mar 2018 - X. Wang - Initial version
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
!
      ! Universal gas consatant [bar/(mol/kg)/K]
      REAL(fp),  PARAMETER   :: con_R     = RStarG*1.0e-2_fp
      ! NO3 MW [kg/mol]
      REAL(fp),  PARAMETER   :: M_NO3  = 6.2e-2_fp

      ! Conversion factor from atm to bar
      REAL(fp),  PARAMETER   :: con_atm_bar = 1.0/1.01325

      REAL(fp)       :: ab, M_X, k, H_X
      REAL(fp)       :: cavg, D_l, gb, l_r

      M_X = M_NO3
      ! Mass accommodation coefficient
      ab = 1.3e-2_fp

      cavg = dsqrt(8.0e+0_fp*RStarG*T/(Pi*M_X)) *1.0e2_fp ! thermal velocity (cm/s)

      ! Liquid phase diffusion coefficient [cm2/s] for HOCl
      ! (Ammann et al., Atmos. Chem. Phys., 2013)
      D_l  = 2.0e-5_fp

      k = 2.76e+6_fp !M-1s-1
      H_X = 0.6e+0_fp !M atm-1
      H_X = H_X * con_atm_bar !M/bar

      l_r = dsqrt(D_l / (k * C_X + 23.0e0_fp*45.0e0_fp))
      gb = 4.0e0_fp * H_X * con_R * T * l_r * (k * C_X + 23.0e0_fp*45.0e0_fp) / cavg

      gb = gb * REACTODIFF_CORR( Radius, l_r)

      GAM_NO3 = 1.0e0_fp / (1.0e0_fp/ab  +  1.0e0_fp/gb)

    END FUNCTION GAMMA_NO3
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: Gamma_HOCl
!
! !DESCRIPTION: Function GAMMA\_HOCl calculates reactive uptake coef.
!               for HOCL + Cl-
!\\
!\\
! !INTERFACE:
!
    FUNCTION GAMMA_HOCl( Radius, n_air, T, C_H, C_X) RESULT(GAM_HOCl)
!
! !USES:
!
      USE PhysConstants,      ONLY : Pi, RStarG
!
! !OUTPUT PARAMETER:
      ! Reactive uptake coefficient (unitless)
      REAL(fp)                       :: GAM_HOCl
! !INPUT PARAMETERS:
!
      REAL(fp), INTENT(IN)           :: Radius   ! Radius (cm)
      REAL(fp), INTENT(IN)           :: n_air    ! n_air (#/cm)
      REAL(fp), INTENT(IN)           :: T        ! Temperature (K)
      REAL(fp), INTENT(IN)           :: C_H      ! H+ concentration
      REAL(fp), INTENT(IN)           :: C_X      ! Cl- Concentration (mol/L)
!
! !REVISION HISTORY:
!  16 Mar 2018 - X. Wang - Initial version
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
!
      ! Universal gas consatant [bar/(mol/kg)/K]
      REAL(fp),  PARAMETER   :: con_R     = RStarG*1.0e-2_fp !bar/(mol/kg)/K
      ! HOCl MW [kg/mol]
      REAL(fp),  PARAMETER   :: M_HOCl  = 5.25e-2_fp

      ! Conversion factor from atm to bar
      REAL(fp),  PARAMETER   :: con_atm_bar = 1.0/1.01325

      ! Henry's constant
      REAL(fp),  PARAMETER   :: H_HOCl    = 6.5e2_fp * con_atm_bar !M/bar
      REAL(fp),  PARAMETER   :: H_HOCl_E  = -5900.0
      REAL(fp),  PARAMETER   :: H_HOCl_T  = 298.15

      REAL(fp)       :: ab, M_X, k_ter, H_X
      REAL(fp)       :: cavg, D_l, gb, l_r

      M_X = M_HOCl
      ! Mass accommodation coefficient
      ab = 0.8e0_fp

      cavg = dsqrt(8.0e+0_fp*RStarG*T/(Pi*M_X)) *1.0e2_fp ! thermal velocity (cm/s)

      ! Liquid phase diffusion coefficient [cm2/s] for HOCl
      ! (Ammann et al., Atmos. Chem. Phys., 2013)
      D_l  = 2.0e-5_fp

      k_ter = 1.5e+4_fp !M-1s-1
      H_X = H_HOCl*dexp(-H_HOCl_E*(1.0e0_fp/T - 1.0e0_fp/H_HOCl_T))

      l_r = dsqrt(D_l / (k_ter * C_H * C_X))
      gb = 4.0e0_fp * H_X * con_R * T * l_r * k_ter * C_H * C_X / cavg
      gb = gb * REACTODIFF_CORR( Radius, l_r)

      GAM_HOCl = 1.0e0_fp / (1.0e0_fp/ab  +  1.0e0_fp/gb)

      GAM_HOCl = MIN(GAM_HOCl, 2.0e-4_fp)

    END FUNCTION GAMMA_HOCl

!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: Gamma_ClNO2
!
! !DESCRIPTION: Function GAMMA\_ClNO2 calculates reactive uptake coef.
!               for ClNO2 + Cl-/Br-
!\\
!\\
! !INTERFACE:
!
    SUBROUTINE GAMMA_ClNO2( Radius, n_air, T, pH, C_X1, C_X2, X, &
                            GAM_ClNO2, r_gp)
!
! !USES:
!
      USE PhysConstants,      ONLY : Pi, RStarG
!
! !OUTPUT PARAMETER:
      ! Reactive uptake coefficient (unitless)
      REAL(fp)                       :: GAM_ClNO2, r_gp
! !INPUT PARAMETERS:
!
      REAL(fp), INTENT(IN)           :: Radius   ! Radius (cm)
      REAL(fp), INTENT(IN)           :: n_air    ! n_air (#/cm)
      REAL(fp), INTENT(IN)           :: T        ! Temperature (K)
      REAL(fp), INTENT(IN)           :: C_X1, C_X2      ! Cl-/Br- Concentration (mol/L)
      INTEGER,  INTENT(IN)           :: X        ! 1=Cl-,2=Br-
      REAL(fp), INTENT(IN)           :: pH
!
! !REVISION HISTORY:
!  25 Jan 2018 - X. Wang - Initial version
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
!
      ! Universal gas consatant [bar/(mol/kg)/K]
      REAL(fp),  PARAMETER   :: con_R     = RStarG*1.0e-2_fp !bar/(mol/kg)/K
      ! ClNO2 MW [kg/mol]
      REAL(fp),  PARAMETER   :: M_ClNO2  = 8.145e-2_fp

      ! Conversion factor from atm to bar
      REAL(fp),  PARAMETER   :: con_atm_bar = 1.0/1.01325

      REAL(fp)       :: ab, M_X, k_ii, H_X, fCl
      REAL(fp)       :: cavg, D_l, gb1, gb2, l_r, gb_tot

      M_X = M_ClNO2
      ! Mass accommodation coefficient
      ab = 0.01e0_fp

      cavg = dsqrt(8.0e+0_fp*RStarG*T/(Pi*M_X)) *1.0e2_fp ! thermal velocity (cm/s)

      ! Liquid phase diffusion coefficient [cm2/s] for ClNO2
      ! (Ammann et al., Atmos. Chem. Phys., 2013)
      D_l  = 1.0e-5_fp
      H_X = 4.5e-2_fp !M atm-1
      H_X = H_X * con_atm_bar !M/bar

      !ClNO2+Cl-
      k_ii = 1.0e+7_fp !M-1s-1
      l_r = dsqrt(D_l / (k_ii * C_X1))
      gb1 = 4.0e0_fp * H_X * con_R * T * l_r * k_ii *C_X1 / cavg
      gb1 = gb1 * REACTODIFF_CORR( Radius, l_r)
      IF (pH >= 2) THEN
         gb1 = 0.0e0_fp
      ENDIF

      !gb1 = 0.0e0_fp

      !ClNO2+Br-
      k_ii = 1.01e-1_fp / (H_X*H_X*D_l)
      l_r = dsqrt(D_l / (k_ii * C_X2))
      gb2 = 4.0e0_fp * H_X * con_R * T * l_r * k_ii *C_X2 / cavg
      gb2 = gb2 * REACTODIFF_CORR( Radius, l_r)

      gb_tot = gb1 + gb2
      GAM_ClNO2 = 1.0e0_fp / (1.0e0_fp/ab  +  1.0e0_fp/gb_tot)

      IF ( X==1 ) THEN
         r_gp = gb1 / gb_tot
      ELSEIF ( X==2 ) THEN
         r_gp = gb2 / gb_tot
      ENDIF

    END SUBROUTINE GAMMA_ClNO2
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetClNO3_SS_JS
!
! !DESCRIPTION: Sets the ClNO3 + Br- (in sea salt) rate using Johan
!  Schmidt's updated code.
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETClNO3_SS_JS( denAir, rAer, AAer, alkAer, TK, clConc, &
                             brConc, X, M) &
                             RESULT( kISum )
!
! !INPUT PARAMETERS: 
!
      REAL(fp), INTENT(IN) :: denAir      ! Density of air (#/cm3)
      REAL(fp), INTENT(IN) :: rAer        ! Radius of aerosol (cm)
      REAL(fp), INTENT(IN) :: AAer        ! Area of aerosol (cm2/cm3)
      REAL(fp), INTENT(IN) :: alkAer      ! Aerosol alkalinity (?)
      REAL(fp), INTENT(IN) :: TK          ! Temperature (K)
      REAL(fp), INTENT(IN) :: clConc      ! Cloride concentration (mol/L)
      REAL(fp), INTENT(IN) :: brConc      ! Bromide concentration (mol/L)
      Integer,  INTENT(IN) :: X           ! 1: Cl-, 2: Br-
      Integer,  INTENT(IN) :: M           ! 1: fine, 2: coarse
!
! !RETURN VALUE:
!
      REAL(fp)             :: kISum
!
! !REMARKS:
!
! !REVISION HISTORY:
!  29 Mar 2016 - R. Yantosca - Added ProTeX header
!  01 Apr 2016 - R. Yantosca - Define N, XSTKCF, ADJUSTEDRATE locally
!  01 Apr 2016 - R. Yantosca - Replace KII_KI with DO_EDUCT local variable
!  22 Dec 2016 - S. D. Eastham - Updated code based on Johan Schmidt's work
!  25 Jan 2018 - X. Wang     - Updated to include both Cl- and Br-
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      INTEGER  :: N
      REAL(fp) :: XSTKCF
      Real(fp), Parameter :: XMolWeight=97.45e+0_fp
      Real(fp), Parameter :: XSQM=SQRT(XMolWeight)
      REAL(fp) :: GAM_ClNO3, r_gp

      ! Initialize
      kISum        = 0.0_fp

      CALL Gamma_ClNO3_AER( rAer, denAir, X, TK, M, clConc, brConc, &
                              GAM_ClNO3, r_gp)
      XStkCf = GAM_ClNO3

      ! Reaction rate for surface of aerosol
      kISum = Arsl1K(AAer,rAer,denAir,XStkCf,XTemp,XSqM) * r_gp 

    END FUNCTION HETClNO3_SS_JS
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetHOBr_SS_JS
!
! !DESCRIPTION: Sets the HOBr + Br- or Cl- (in sea salt) rate using Johan
!  Schmidt's updated code.
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETHOBr_SS_JS( denAir, rAer, AAer, alkAer, TK, hConc, clConc, &
                            brConc, X) &
                            RESULT( kISum )
!
! !INPUT PARAMETERS: 
!
      REAL(fp), INTENT(IN) :: denAir      ! Density of air (#/cm3)
      REAL(fp), INTENT(IN) :: rAer        ! Radius of aerosol (cm)
      REAL(fp), INTENT(IN) :: AAer        ! Area of aerosol (cm2/cm3)
      REAL(fp), INTENT(IN) :: alkAer      ! Aerosol alkalinity (?)
      REAL(fp), INTENT(IN) :: TK          ! Temperature (K)
      REAL(fp), INTENT(IN) :: hConc       ! H+ concentration (mol/L)
      REAL(fp), INTENT(IN) :: clConc      ! Cloride concentration (mol/L)
      REAL(fp), INTENT(IN) :: brConc      ! Bromide concentration (mol/L)
      Integer,  INTENT(IN) :: X           ! 1: Cl-, 2: Br-
!
! !RETURN VALUE:
!
      REAL(fp)             :: kISum
!
! !REMARKS:
!
! !REVISION HISTORY:
!  29 Mar 2016 - R. Yantosca - Added ProTeX header
!  01 Apr 2016 - R. Yantosca - Define N, XSTKCF, ADJUSTEDRATE locally
!  01 Apr 2016 - R. Yantosca - Replace KII_KI with DO_EDUCT local variable
!  22 Dec 2016 - S. D. Eastham - Updated code based on Johan Schmidt's work
!  01 Dec 2017 - Q.J. Chen     - Updated to account for Cl- and Br- separately;
!                                Now calls routine Gamma_HOBr_AER
!  25 Jam 2018 - X. Wang     - Updated to include Cl-(p)
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      INTEGER  :: N
      REAL(fp) :: XSTKCF, ADJUSTEDRATE
      Real(fp), Parameter :: XMolWeight=96.9e+0_fp
      Real(fp), Parameter :: XSQM=SQRT(XMolWeight)
      REAL(fp) :: GAM_HOBr, r_gp

      ! Initialize
      kISum        = 0.0_fp
      ADJUSTEDRATE = 0.0_fp

      ! Reaction can only proceed on acidic aerosol
      IF (alkAer > 0.05e+0_fp) THEN
         XStkCf = 0.0_fp
         r_gp = 0.0_fp
      ELSE
         CALL Gamma_HOBr_AER(rAer, denAir, X, TK, clConc, brConc, &
                             hConc, GAM_HOBr, r_gp)
         XStkCf = GAM_HOBr
      ENDIF

      ! Reaction rate for surface of aerosol
      kISum = Arsl1K(AAer,rAer,denAir,XStkCf,XTemp,XSqM)*r_gp

    END FUNCTION HETHOBr_SS_JS
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetO3_HBr_JS
!
! !DESCRIPTION: Sets the O3 + Br- rate using Johan Schmidt's
!  updated code.
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETO3_HBr_JS( denAir, rLiq, rIce, ALiq, AIce, VAir, TK, brConc_a, brConc_c, brConc_g, O3Conc, X ) RESULT( kISum )
!
! !INPUT PARAMETERS: 
!
      REAL(fp), INTENT(IN) :: denAir      ! Density of air (#/cm3)
      REAL(fp), INTENT(IN) :: rLiq        ! Radius of liquid cloud droplets (cm)
      REAL(fp), INTENT(IN) :: rIce        ! Radius of ice cloud crystals (cm)
      REAL(fp), INTENT(IN) :: ALiq        ! Area of liquid cloud droplets (cm2/cm3)
      REAL(fp), INTENT(IN) :: AIce        ! Area of ice cloud crystals (cm2/cm3)
      REAL(fp), INTENT(IN) :: VAir        ! Box volume (cm3)
      REAL(fp), INTENT(IN) :: TK          ! Temperature (K)
      REAL(fp), INTENT(IN) :: brConc_a    ! Bromide concentration (mol/L)
      REAL(fp), INTENT(IN) :: brConc_c    ! Bromide concentration (mol/L)
      REAL(fp), INTENT(IN) :: brConc_g    ! Bromide concentration (mol/L)
      REAL(fp), INTENT(IN) :: O3Conc      ! Ozone concentration (mol/L)
      INTEGER, INTENT(IN) :: X           ! X=1 _a; 2 _c; 3 _g
!
! !RETURN VALUE:
!
      REAL(fp)             :: kISum
!
! !REMARKS:
!
! !REVISION HISTORY:
!  29 Mar 2016 - R. Yantosca - Added ProTeX header
!  01 Apr 2016 - R. Yantosca - Define N, XSTKCF, ADJUSTEDRATE locally
!  01 Apr 2016 - R. Yantosca - Replace KII_KI with DO_EDUCT local variable
!  22 Dec 2016 - S. D. Eastham - Updated code based on Johan Schmidt's work
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      INTEGER  :: N
      REAL(fp) :: XSTKCF, ADJUSTEDRATE, brConc, r_ac
      Real(fp), Parameter :: XMolWeight=48.0e+0_fp
      Real(fp), Parameter :: XSQM=SQRT(XMolWeight)

      ! Initialize
      kISum        = 0.0_fp
      ADJUSTEDRATE = 0.0_fp
      XSTKCF       = 0.0_fp
      r_ac         = 0.0_fp
      brConc       = 0.0_fp

      brConc = brConc_a + brConc_g + brConc_c

      IF (X.EQ.1) THEN
         r_ac = brConc_a / brConc
      ELSE IF (X .EQ. 2) THEN
         r_ac = brConc_c / brConc
      ELSE
         r_ac = brConc_g / brConc
      ENDIF

      ! Loop over aerosol types
      DO N = 1, NAERO

         ! Get the aerosol type
         XStkCf = 0.0e+0_fp
         !IF ( N == 8 ) THEN
            ! sulfate aerosol
            !XSTKCF = Gamma_O3_Br( xRadi(8), denAir, TK, brConc, O3Conc )
            ! Move this to + BrSALA, xnw
         !ENDIF

         IF (XStkCf.gt.0.0e+0_fp) THEN
            IF (N.eq.13) THEN
               ! Calculate for stratospheric liquid aerosol
               ! Note that XSTKCF is actually a premultiplying
               ! factor in this case, including c-bar
               ADJUSTEDRATE = XAREA(N) * XSTKCF
            ELSE
               ! Reaction rate for surface of aerosol
               ADJUSTEDRATE=ARSL1K(XAREA(N),XRADI(N),XDENA,XSTKCF,XTEMP,XSQM)
            ENDIF
            
            ! Add to overall reaction rate
            kISum = kISum + ADJUSTEDRATE*r_ac
         ENDIF
      END DO

    ! Reaction on liquid and ice clouds (tropospheric only)
    IF (.not. StratBox) THEN
       IF (ALiq.gt.0.0e+0_fp) THEN
          XStkCf = Gamma_O3_Br( rLiq, denAir, TK, brConc, O3Conc )
          kISum = kISum + Arsl1K(ALiq, rLiq, denAir, XStkCf, XTemp, XSqM)*r_ac
       ENDIF
       IF (AIce.gt.0.0e+0_fp) THEN
          XStkCf = Gamma_O3_Br( rIce, denAir, TK, brConc, O3Conc )
          kISum = kISum + Arsl1K(AIce, rIce, denAir, XStkCf, XTemp, XSqM)*r_ac
       ENDIF
    ENDIF

    END FUNCTION HETO3_HBr_JS
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: Gamma_O3_Br
!
! !DESCRIPTION: Function GAMMA\_O3\_Br calculates reactive uptake coef.
!               for bromide oxidation by O3
!\\
!\\
! !INTERFACE:
!
      FUNCTION GAMMA_O3_Br( Radius, n_air, T, C_Y, C_X_g ) RESULT( GAM )  
!
! !USES:
!
  USE PhysConstants,      ONLY : Pi, RStarG
!
! !OUTPUT PARAMETER:
      ! Reactive uptake coefficient (unitless)
      REAL(fp)                         :: GAM
! !INPUT PARAMETERS:
!
      ! Radius (cm), n_air (#/cm), and X (1 for Cl and 2 for Br)
      REAL(fp), INTENT(IN)             :: Radius, n_air
      REAL(fp), INTENT(IN)             :: T, C_Y, C_X_g
!
! !REVISION HISTORY:
!  24 Sept 2015 - J. Schmidt - Initial version
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
!
      REAL(fp),  PARAMETER   :: con_atm_bar = 1.0/1.01325
!      REAL(fp),  PARAMETER   :: con_pi      = 3.14159265359e0_fp
!      REAL(fp),  PARAMETER   :: con_R_SI    = 8.3144621e0_fp  !J/(K*mol)
!      REAL(fp),  PARAMETER   :: con_R       = 8.3144621e-2_fp !bar/(mol/kg)/K
      REAL(fp),  PARAMETER   :: con_R     = RStarG*1.0e-2_fp !bar/(mol/kg)/K
      ! O3
      REAL(fp),  PARAMETER   :: H_O3      = 1.1e-2_fp * con_atm_bar 
      REAL(fp),  PARAMETER   :: H_O3_E    = -2300.0
      REAL(fp),  PARAMETER   :: H_O3_T    = 298.15
      REAL(fp),  PARAMETER   :: M_O3      = 4.8e-2_fp

      REAL(fp)       :: ab, gb, gd, gs, M_X
      REAL(fp)       :: cavg, H_X
      REAL(fp)       :: KLangC, k_s, C_Y_surf, Nmax
      REAL(fp)       :: k_b, D_l, l_r

      H_X = H_O3*dexp(-H_O3_E*(1.0e0_fp/T - 1.0e0_fp/H_O3_T))
      M_X = M_O3

      cavg    = dsqrt(8*RStarG*T/(Pi*M_X)) *1.0e2_fp ! thermal velocity (cm/s)

      Nmax = 3.0e14_fp ! #/cm2
      KLangC = 1.0e-13_fp !cm3
      k_s = 1.0e-16_fp !cm2s-1, from ks*Nmax=0.03s-1
      C_Y_surf= min(3.41e14_fp*C_Y, Nmax) ! [Br-(surf)] = 3.41E14 cm-2/M * [Br-(bulk)], but not gt Nmax.
      gs = (4.0e0_fp * k_s * C_Y_surf * KLangC * Nmax) / &
                    (cavg * (1.0e0_fp + KLangC * C_X_g) )

      k_b = 6.3e8_fp *  dexp(-4.45e3_fp / T) !M-1 s-1
      D_l = 8.9e-6_fp !cm2 s-1. 
      l_r = dsqrt( D_l / (k_b * C_Y ) )! cm
      gb  = 4.0e0_fp * H_X * con_R * T * l_r * k_b * C_Y / cavg 
      gb  = gb * REACTODIFF_CORR( Radius, l_r) 

      GAM = gb + gs

      END FUNCTION GAMMA_O3_Br
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetClNO3_HBr_JS
!
! !DESCRIPTION: Sets the ClNO3 + Br- rate using Johan Schmidt's
!  updated code.
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETClNO3_HBr_JS( A, B ) RESULT( kISum )
!
! !INPUT PARAMETERS:

! Rate coefficients
      REAL(fp), INTENT(IN) :: A, B
!
! !RETURN VALUE:
!
      REAL(fp)             :: kISum
!
! !REMARKS:
!
! !REVISION HISTORY:
!  29 Mar 2016 - R. Yantosca - Added ProTeX header
!  01 Apr 2016 - R. Yantosca - Define N, XSTKCF, ADJUSTEDRATE locally
!  01 Apr 2016 - R. Yantosca - Replace KII_KI with DO_EDUCT local variable
!  22 Dec 2016 - S. D. Eastham - Updated code based on Johan Schmidt's work
!  25 Jan 2018 - X. Wang     - Move reactions on troposphere cloud to
!                              HETClNO3_TCld
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      INTEGER  :: N
      REAL(fp) :: XSTKCF, ADJUSTEDRATE
      Real(fp) :: XSQM

      ! Initialize
      kISum        = 0.0_fp
      ADJUSTEDRATE = 0.0_fp
      XSTKCF       = 0.0_fp
      XSQM         =sqrt(A)

      ! Loop over aerosol types
      DO N = 1, NAERO

         ! Get the aerosol type
         XStkCf = 0.0e+0_fp
         IF ( N == 8 ) THEN
            ! sulfate aerosol
            ! This seems not to happen
#if defined( UCX )
         ELSEIF (STRATBOX) THEN
            IF (N.eq.13) THEN
               XSTKCF = KHETI_SLA(5)
            ELSEIF (N.eq.14) THEN
               IF (NATSURFACE) THEN
                  XSTKCF = 0.3e+0_fp ! NAT
               ELSE
                  XSTKCF = 0.3e+0_fp ! Ice
               ENDIF
            ENDIF
#endif
         ENDIF

         IF (XStkCf.gt.0.0e+0_fp) THEN
            IF (N.eq.13) THEN
               ! Calculate for stratospheric liquid aerosol
               ! Note that XSTKCF is actually a premultiplying
               ! factor in this case, including c-bar
               ADJUSTEDRATE = XAREA(N) * XSTKCF
            ELSE
               ! Reaction rate for surface of aerosol
               ADJUSTEDRATE=ARSL1K(XAREA(N),XRADI(N),XDENA,XSTKCF,XTEMP,XSQM)
            ENDIF
            
            ! Add to overall reaction rate
            kISum = kISum + ADJUSTEDRATE
         ENDIF
      END DO

    END FUNCTION HETClNO3_HBr_JS
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetClNO3_JS
!
! !DESCRIPTION: Sets the hydrolysis rate for ClNO3 using Johan Schmidt's
!  updated code.
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETClNO3_JS( denAir, rLiq, rIce, ALiq, AIce, TK, clconc, brconc, clcld, brcld,CF ) RESULT( HET_ClNO3 )
!
! !INPUT PARAMETERS: 
!
      REAL(fp), INTENT(IN) :: denAir      ! Density of air (#/cm3)
      REAL(fp), INTENT(IN) :: rLiq        ! Radius of liquid cloud droplets (cm)
      REAL(fp), INTENT(IN) :: rIce        ! Radius of ice cloud crystals (cm)
      REAL(fp), INTENT(IN) :: ALiq        ! Area of liquid cloud droplets (cm2/cm3)
      REAL(fp), INTENT(IN) :: AIce        ! Area of ice cloud crystals (cm2/cm3)
      REAL(fp), INTENT(IN) :: TK          ! Temperature (K)
      REAL(fp), INTENT(IN) :: clconc, brconc   ! Cl-/Br- concentration in fine mode (M)
      REAL(fp), INTENT(IN) :: clcld, brcld   ! Cl-/Br- concentration in cloud (M)
      REAL(fp), INTENT(IN) :: CF          ! Cloud fraction
!
! !RETURN VALUE:
!
      REAL(fp)             :: HET_ClNO3
!
! !REMARKS:
!
! !REVISION HISTORY:
!  29 Mar 2016 - R. Yantosca - Added ProTeX header
!  01 Apr 2016 - R. Yantosca - Define N, XSTKCF, ADJUSTEDRATE locally
!  01 Apr 2016 - R. Yantosca - Replace KII_KI with DO_EDUCT local variable
!  16 Dec 2016 - S. D. Eastham - Updated code based on Johan Schmidt's work
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      LOGICAL  :: DO_EDUCT
      INTEGER  :: N
      REAL(fp) :: XSTKCF, ADJUSTEDRATE
      Real(fp), Parameter :: XMolWeight=97.5e+0_fp
      Real(fp), Parameter :: XSQM=SQRT(XMolWeight)
      Real(fp) ::  GAM_ClNO3, r_gp

      ! Initialize
      HET_ClNO3    = 0.0_fp
      ADJUSTEDRATE = 0.0_fp
      XSTKCF       = 0.0_fp
      GAM_ClNO3    = 0.0_fp
      r_gp         = 0.0_fp

      ! Only apply PSC rate adjustment if at high altitude
      DO_EDUCT     = STRATBOX

      ! Loop over aerosol types
      DO N = 1, NAERO
         XSTKCF = 0e+0_fp
         ! Get the aerosol type
         IF ( N == 8 ) THEN
            ! Follow ClNO3 + Cl- channel
            XSTKCF = 0e+0_fp
         ELSEIF (N == 11) THEN
            ! Follow ClNO3 + Cl- channel, xnw 1/25/18
            CALL GAMMA_ClNO3_AER(AClRADI, denAir, 3, TK, 3, clconc, brconc, &
                              GAM_ClNO3, r_gp)
            XSTKCF = GAM_ClNO3
         ELSEIF (N == 12) THEN
            ! Follow ClNO3 + Cl- channel
            XSTKCF = 0e+0_fp
         ELSEIF (N.eq.13) THEN
            XSTKCF = KHETI_SLA(3)
         ELSEIF (N.eq.14) THEN
            IF (NATSURFACE) THEN
               XSTKCF = 0.004e+0_fp ! NAT
            ELSE
               XSTKCF = 0.3e+0_fp ! Ice
            ENDIF
         ELSE
            XSTKCF = 0e+0_fp
         ENDIF

         IF (N.eq.13) THEN
            ! Calculate for stratospheric liquid aerosol
            ! Note that XSTKCF is actually a premultiplying
            ! factor in this case, including c-bar
            ADJUSTEDRATE = XAREA(N) * XSTKCF
         ELSE IF (N .eq. 11) THEN
            ADJUSTEDRATE =ARSL1K((1-CF)*AClAREA,AClRADI,XDENA,XSTKCF,XTEMP,XSQM)*r_gp
         ELSE
            ! Reaction rate for surface of aerosol
            ADJUSTEDRATE=ARSL1K(XAREA(N),XRADI(N),XDENA,XSTKCF,XTEMP,XSQM)
         ENDIF
         
         ! Add to overall reaction rate
         HET_ClNO3 = HET_ClNO3 + ADJUSTEDRATE
      END DO

    ! Hydrolysis on liquid and ice clouds (tropospheric only)
    IF (.not. StratBox) THEN
       !HET_ClNO3 = HET_ClNO3 + Cld1K_XNO3(denAir,TK,rLiq,rIce,ALiq,AIce,XMolWeight,2.4E-2_fp)
       CALL GAMMA_ClNO3_AER(rLiq, denAir, 3, TK, 3, clcld, brcld, GAM_ClNO3, r_gp)
       XSTKCF = GAM_ClNO3       
       ADJUSTEDRATE =ARSL1K(ALiq,rLiq,XDENA,XSTKCF,XTEMP,XSQM)*r_gp
       HET_ClNO3 = HET_ClNO3 + ADJUSTEDRATE

       CALL GAMMA_ClNO3_AER(rIce, denAir, 3, TK, 3, clcld, brcld, GAM_ClNO3, r_gp)
       XSTKCF = GAM_ClNO3     
       ADJUSTEDRATE =ARSL1K(AIce,rIce,XDENA,XSTKCF,XTEMP,XSQM)*r_gp
       HET_ClNO3 = HET_ClNO3 + ADJUSTEDRATE

    ENDIF

    END FUNCTION HETClNO3_JS
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetHOBr_HCl_JS
!
! !DESCRIPTION: Sets the rate of the multiphase reaction HOBr + Cl- in 
!  sulfate aerosols, on cloud droplets and on PSCs
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETHOBr_HCl_JS( A, B ) RESULT( kISum )
!
! Rate coefficients
      REAL(fp), INTENT(IN) :: A, B
!
! !RETURN VALUE:
!
      REAL(fp)             :: kISum
!
! !REMARKS:
!
! !REVISION HISTORY:
!  21 Dec 2016 - S. D. Eastham - Generated code based on Johan Schmidt's work
!  01 Dec 2017 - Q.J. Chen     - Updated to account for Br-, HSO3-, and SO3--;
!                                Now calls routine Gamma_HOBr_AER
!  25 Jan 2018 - X. Wang       - Move reactions on troposphere cloud to
!                                HetHOBr_TCld 
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      INTEGER  :: N
      REAL(fp) :: XSTKCF, ADJUSTEDRATE
      Real(fp) :: XSQM
      REAL(fp) :: GAM_HOBr, r_gp

      ! Initialize
      kISum        = 0.0_fp
      ADJUSTEDRATE = 0.0_fp
      XSTKCF       = 0.0_fp
      XSQM         = SQRT(A)

      ! Loop over aerosol types
      DO N = 1, NAERO

         XSTKCF = 0e+0_fp
         ! Get the aerosol type
#if defined( UCX )         
         IF (STRATBOX) THEN
            ! add limitation to stratosphere, xnw 1/25/18
            IF ( N == 8 ) THEN
               XSTKCF = 0.2e+0_fp ! Sulfate, [Hanson and Ravishankara, 1995]
            ELSEIF (N.eq.13) THEN
               ! SSA/STS
               XSTKCF = KHETI_SLA(10)
            ELSEIF (N.eq.14) THEN
               ! Ice/NAT PSC
               IF (NATSURFACE) THEN
                  XSTKCF = 0.1e+0_fp ! NAT
               ELSE
                  XSTKCF = 0.3e+0_fp ! Ice
               ENDIF
            ELSE
               XSTKCF = 0e+0_fp
            ENDIF
         ENDIF
#endif

         IF (N.eq.13) THEN
            ! Calculate for stratospheric liquid aerosol
            ! Note that XSTKCF is actually a premultiplying
            ! factor in this case, including c-bar
            ADJUSTEDRATE = XAREA(N) * XSTKCF
         ELSEIF (XStkCf.gt.0.0e+0_fp) THEN
            ! Reaction rate for surface of aerosol
            ADJUSTEDRATE=ARSL1K(XAREA(N),XRADI(N),XDENA,XSTKCF,XTEMP,XSQM)
         ENDIF
         
         ! Add to overall reaction rate
         kISum = kISum + ADJUSTEDRATE
      END DO

    END FUNCTION HETHOBr_HCl_JS
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetHOBr_HBr_JS
!
! !DESCRIPTION: Sets the rate of the multiphase reaction HOBr + Br- in 
!  sulfate aerosols, on cloud droplets and on PSCs
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETHOBr_HBr_JS( A, B ) RESULT( kISum )
!
! Rate coefficients
      REAL(fp), INTENT(IN) :: A, B
!
! !RETURN VALUE:
!
      REAL(fp)             :: kISum
!
! !REMARKS:
!
! !REVISION HISTORY:
!  21 Dec 2016 - S. D. Eastham - Generated code based on Johan Schmidt's work
!  01 Dec 2017 - Q.J. Chen     - Updated to account for Cl-, HSO3-, and SO3--;
!                                Now calls routine Gamma_HOBr_AER
!  25 Jan 2017 - X. Wang       - Move HOBr + Br- in troposphere cloud to
!                                HETHOBr_TCld 
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      INTEGER  :: N
      REAL(fp) :: XSTKCF, ADJUSTEDRATE
      Real(fp) :: XSQM
      Real(fp) :: SADen

      ! Initialize
      kISum        = 0.0_fp
      ADJUSTEDRATE = 0.0_fp
      XSTKCF       = 0.0_fp
      XSQM=SQRT(A)

      ! Loop over aerosol types
      DO N = 1, NAERO
         XSTKCF = 0e+0_fp
         ! Get the aerosol type
#if defined( UCX )         
         IF (STRATBOX) THEN
            ! add limitation to stratosphere, xnw 1/25/18
            IF ( N == 8 ) THEN
               XSTKCF = 0.25e+0_fp ! Sulfate, [Abbatt, 1995]          
            ELSEIF ( N == 13 ) THEN
               ! SSA/STS
               XSTKCF = KHETI_SLA(6)
            ELSEIF ( N == 14 ) THEN 
               ! Ice/NAT PSC
               IF (NATSURFACE) THEN 
                  XSTKCF = 0.001e+0_fp
               ELSE
                  XSTKCF = 0.3e+0_fp
               ENDIF
            ELSE
               XSTKCF = 0e+0_fp
            ENDIF
         ENDIF
#endif

         IF (N.eq.13) THEN
            ! Calculate for stratospheric liquid aerosol
            ! Note that XSTKCF is actually a premultiplying
            ! factor in this case, including c-bar
            ADJUSTEDRATE = XAREA(N) * XSTKCF
         ELSEIF (XStkCf.gt.0.0e+0_fp) THEN
            ! Reaction rate for surface of aerosol
            ADJUSTEDRATE=ARSL1K(XAREA(N),XRADI(N),XDENA,XSTKCF,XTemp,XSQM)
         ENDIF
         
         ! Add to overall reaction rate
         kISum = kISum + ADJUSTEDRATE
      END DO

    END FUNCTION HETHOBr_HBr_JS
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetClNO3_TCld
!
! !DESCRIPTION: Sets the rate of the multiphase reaction ClNO3 + Cl-/Br- in
!  troposphere cloud
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETClNO3_TCld( denAir, rLiq, rIce, ALiq, AIce, VAir, TK, &
                           clConc_A, clConc_C, clConc_g,&
                           brConc_A, brConc_C, brConc_g, X) &
                           RESULT( kISum )

!
! !INPUT PARAMETERS:
!
      REAL(fp), INTENT(IN) :: denAir      ! Density of air (#/cm3)
      REAL(fp), INTENT(IN) :: rLiq        ! Radius of liquid cloud droplets (cm)
      REAL(fp), INTENT(IN) :: rIce        ! Radius of ice cloud crystals (cm)
      REAL(fp), INTENT(IN) :: ALiq        ! Area of liquid cloud droplets (cm2/cm3)
      REAL(fp), INTENT(IN) :: AIce        ! Area of ice cloud crystals (cm2/cm3)
      REAL(fp), INTENT(IN) :: VAir        ! Box volume (cm3)
      REAL(fp), INTENT(IN) :: TK          ! Temperature (K)
      REAL(fp), INTENT(IN) :: clConc_A    ! Fine Chloride concentration (mol/L)
      REAL(fp), INTENT(IN) :: clConc_C    ! Coarse Chloride concentration (mol/L)
      REAL(fp), INTENT(IN) :: clConc_g    
      REAL(fp), INTENT(IN) :: brConc_A    ! Fine Bromide concentration (mol/L)
      REAL(fp), INTENT(IN) :: brConc_C    ! Coarse Bromide concentration (mol/L)
      REAL(fp), INTENT(IN) :: brConc_g
      INTEGER,  INTENT(IN) :: X           ! 1=fineCl;2=coarseCl;3=fineBr;4=coarseBr;5=HCl;6=HBr
!
! !RETURN VALUE:
!
      REAL(fp)             :: kISum
!
 !REMARKS:
!
! !REVISION HISTORY:
!  01 Feb 2018 - X. Wang      - Initial version
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      INTEGER  :: N, Y, M
      REAL(fp) :: XSTKCF, ADJUSTEDRATE
      Real(fp), Parameter :: XMolWeight=97.45e+0_fp
      Real(fp), Parameter :: XSQM=SQRT(XMolWeight)
      REAL(fp) :: GAM_ClNO3, r_gp, clConc, r_ac, brConc

      ! Initialize
      kISum        = 0.0_fp
      ADJUSTEDRATE = 0.0_fp
      XSTKCF       = 0.0_fp

      ! Cloud halide concentration, put fine and coarse mode together
      clConc = clConc_A + clConc_C + clConc_g
      brConc = brConc_A + brConc_C + brConc_g

      If (X == 1) THEN
         Y = 1
         M = 3
         r_ac = clConc_A / clConc
      ELSEIF (X == 2) THEN
         Y = 1
         M = 2
         r_ac = clConc_C / clConc
      ElSEIF (X == 3) THEN
         Y = 2
         M = 3
         r_ac = brConc_A / brConc
      ELSEIF (X == 4) THEN
         Y = 2
         M = 2
         r_ac = brConc_C / brConc
      ELSEIF (X == 5) THEN
         Y = 1
         M = 3
         r_ac = clConc_g / clConc
      ELSEIF (X == 6) THEN
         Y = 2
         M = 3
         r_ac = brConc_g / brConc
      ENDIF

      IF (.not. StratBox) THEN
       IF (ALiq.gt.0.0e+0_fp) THEN
          CALL Gamma_ClNO3_AER(rLiq, denAir, Y, TK, M, clConc, brConc, &
                               GAM_ClNO3, r_gp)
          XSTKCF = GAM_ClNO3
          kISum = kISum + Arsl1K(ALiq, rLiq, denAir, XStkCf, XTemp, XSqM)*r_gp*r_ac
       ENDIF
       IF (AIce.gt.0.0e+0_fp) THEN
          CALL Gamma_ClNO3_AER(rIce, denAir, Y, TK, M, clConc, brConc, &
                               GAM_ClNO3, r_gp)
          XSTKCF = GAM_ClNO3
          kISum = kISum + Arsl1K(AIce, rIce, denAir, XStkCf, XTemp, XSqM)*r_gp*r_ac
       ENDIF
      ENDIF

    END FUNCTION HetClNO3_TCld
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetHOBr_TCld
!
! !DESCRIPTION: Sets the rate of the multiphase reaction HOBr + Cl-/Br- in
!  troposphere cloud
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETHOBr_TCld( denAir, rLiq, rIce, ALiq, AIce, VAir, TK, &
                           hConc_Sul, hConc_LCl, hConc_ICl, clConc_A, clConc_C, clConc_g, &
                           brConc_A, brConc_C, brConc_g, hso3Conc, so3Conc, X ) &
                           RESULT( kISum )

!
! !INPUT PARAMETERS:
!
      REAL(fp), INTENT(IN) :: denAir      ! Density of air (#/cm3)
      REAL(fp), INTENT(IN) :: rLiq        ! Radius of liquid cloud droplets (cm)
      REAL(fp), INTENT(IN) :: rIce        ! Radius of ice cloud crystals (cm)
      REAL(fp), INTENT(IN) :: ALiq        ! Area of liquid cloud droplets (cm2/cm3)
      REAL(fp), INTENT(IN) :: AIce        ! Area of ice cloud crystals (cm2/cm3)
      REAL(fp), INTENT(IN) :: VAir        ! Box volume (cm3)
      REAL(fp), INTENT(IN) :: TK          ! Temperature (K)
      REAL(fp), INTENT(IN) :: hConc_Sul   ! Sulfate H+ concentration
      REAL(fp), INTENT(IN) :: hConc_LCl   ! Liquid cloud H+ concentration
      REAL(fp), INTENT(IN) :: hConc_ICl   ! Ice cloud H+ concentration
      REAL(fp), INTENT(IN) :: clConc_A    ! Fine Chloride concentration (mol/L)
      REAL(fp), INTENT(IN) :: clConc_C    ! Coarse Chloride concentration (mol/L)
      REAL(fp), INTENT(IN) :: clConc_g
      REAL(fp), INTENT(IN) :: brConc_A    ! Fine Bromide concentration (mol/L)
      REAL(fp), INTENT(IN) :: brConc_C    ! Coarse Bromide concentration (mol/L)
      REAL(fp), INTENT(IN) :: brConc_g
      REAL(fp), INTENT(IN) :: hso3Conc    ! HSO3-    concentration (mol/L)
      REAL(fp), INTENT(IN) :: so3Conc     ! SO3--    concentration (mol/L)
      INTEGER,  INTENT(IN) :: X           ! 1=fineCl;2=coarseCl;3=fineBr;4=coarseBr;5=HCl;6=HBr
!
! !RETURN VALUE:
!
      REAL(fp)             :: kISum
!
 !REMARKS:
!
! !REVISION HISTORY:
!  01 Feb 2018 - X. Wang      - Initial version
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      INTEGER  :: N, Y
      REAL(fp) :: XSTKCF, ADJUSTEDRATE
      Real(fp), Parameter :: XMolWeight=96.9e+0_fp
      Real(fp), Parameter :: XSQM=SQRT(XMolWeight)
      REAL(fp) :: GAM_HOBr, r_gp, clConc, r_ac, brConc

      ! Initialize
      kISum        = 0.0_fp
      ADJUSTEDRATE = 0.0_fp
      XSTKCF       = 0.0_fp

      ! Cloud halide concentration, put fine and coarse mode together
      clConc = clConc_A + clConc_C + clConc_g
      brConc = brConc_A + brConc_C + brConc_g

      If (X == 1) THEN 
         Y = 1 
         r_ac = clConc_A / clConc
      ELSEIF (X == 2) THEN
         Y = 1 
         r_ac = clConc_C / clConc
      ElSEIF (X == 3) THEN
         Y = 2 
         r_ac = brConc_A / brConc
      ELSEIF (X == 4) THEN
         Y = 2
         r_ac = brConc_C / brConc
      ELSEIF (X == 5) THEN
         Y = 1
         r_ac = clConc_g / clConc
      ELSEIF (X == 6) THEN
         Y = 2
         r_ac = brConc_g / brConc
      ENDIF 

      IF (.not. StratBox) THEN
       IF (ALiq.gt.0.0e+0_fp) THEN
          CALL Gamma_HOBr_CLD(rLiq, denAir, Y, TK, clConc, brConc, &
                              hso3Conc, so3Conc, hConc_LCl, GAM_HOBr, r_gp)
          XSTKCF = GAM_HOBr         
          kISum = kISum + Arsl1K(ALiq, rLiq, denAir, XStkCf, XTemp, XSqM)*r_gp*r_ac
       ENDIF
       IF (AIce.gt.0.0e+0_fp) THEN
          CALL Gamma_HOBr_CLD(rIce, denAir, Y, TK, clConc, brConc, &
                              hso3Conc, so3Conc, hConc_ICl, GAM_HOBr, r_gp)
          XSTKCF = GAM_HOBr
          kISum = kISum + Arsl1K(AIce, rIce, denAir, XStkCf, XTemp, XSqM)*r_gp*r_ac
       ENDIF
      ENDIF

    END FUNCTION HetHOBr_TCld
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetHOBr_HSO3
!
! !DESCRIPTION: Sets the rate of the multiphase reaction HOBr + HSO3- in 
!  sulfate aerosols, on cloud droplets and on PSCs
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETHOBr_HSO3( denAir, rLiq, rIce, ALiq, AIce, VAir, TK, &
                           hConc_Sul, hConc_LCl, hConc_ICl, clConc, brConc, &
                           hso3Conc, so3Conc ) &
                           RESULT( kISum )
!
! !INPUT PARAMETERS: 
!
      REAL(fp), INTENT(IN) :: denAir      ! Density of air (#/cm3)
      REAL(fp), INTENT(IN) :: rLiq        ! Radius of liquid cloud droplets (cm)
      REAL(fp), INTENT(IN) :: rIce        ! Radius of ice cloud crystals (cm)
      REAL(fp), INTENT(IN) :: ALiq        ! Area of liquid cloud droplets (cm2/cm3)
      REAL(fp), INTENT(IN) :: AIce        ! Area of ice cloud crystals (cm2/cm3)
      REAL(fp), INTENT(IN) :: VAir        ! Box volume (cm3)
      REAL(fp), INTENT(IN) :: TK          ! Temperature (K)
      REAL(fp), INTENT(IN) :: hConc_Sul   ! Sulfate H+ concentration
      REAL(fp), INTENT(IN) :: hConc_LCl   ! Liquid cloud H+ concentration
      REAL(fp), INTENT(IN) :: hConc_ICl   ! Ice cloud H+ concentration
      REAL(fp), INTENT(IN) :: clConc      ! Chloride concentration (mol/L), qjc
      REAL(fp), INTENT(IN) :: brConc      ! Bromide  concentration (mol/L), qjc
      REAL(fp), INTENT(IN) :: hso3Conc    ! HSO3-    concentration (mol/L)
      REAL(fp), INTENT(IN) :: so3Conc     ! SO3--    concentration (mol/L), qjc
!
! !RETURN VALUE:
!
      REAL(fp)             :: kISum
!
! !REMARKS:
!
! !REVISION HISTORY:
!  15 Nov 2017 - M. Sulprizio  - Generated code based on Qianjie Chen's work
!  01 Dec 2017 - Q.J. Chen     - Updated to account for Cl-, Br-, and SO3--;
!                                Now calls routine Gamma_HOBr_CLD
!                                Remove HOBr+S(IV) on sulfate aerosols
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      INTEGER  :: N
      REAL(fp) :: XSTKCF, ADJUSTEDRATE
      Real(fp), Parameter :: XMolWeight=96.9e+0_fp
      Real(fp), Parameter :: XSQM=SQRT(XMolWeight)
      REAL(fp) :: GAM_HOBr, r_gp

      ! Initialize
      kISum        = 0.0_fp
      ADJUSTEDRATE = 0.0_fp
      XSTKCF       = 0.0_fp

      ! Loop over aerosol types
      DO N = 1, NAERO
         XSTKCF = 0e+0_fp
         ! Get the aerosol type
         IF ( N == 8 ) THEN
            ! No HOBr+S(IV) on sulfate aerosols
            XSTKCF = 0e+0_fp
         ELSEIF (N.eq.13) THEN
            ! SSA/STS
            XSTKCF = KHETI_SLA(10)
         ELSEIF (N.eq.14) THEN
            ! Ice/NAT PSC
            IF (NATSURFACE) THEN
               XSTKCF = 0.1e+0_fp ! NAT
            ELSE
               XSTKCF = 0.3e+0_fp ! Ice
            ENDIF
         ELSE
            XSTKCF = 0e+0_fp
         ENDIF

         IF (N.eq.13) THEN
            ! Calculate for stratospheric liquid aerosol
            ! Note that XSTKCF is actually a premultiplying
            ! factor in this case, including c-bar
            ADJUSTEDRATE = XAREA(N) * XSTKCF
         ELSE
            ! Reaction rate for surface of aerosol
            ADJUSTEDRATE=ARSL1K(XAREA(N),XRADI(N),XDENA,XSTKCF,XTEMP,XSQM)
         ENDIF
         
         ! Add to overall reaction rate
         kISum = kISum + ADJUSTEDRATE
      END DO

    ! Hydrolysis on liquid and ice clouds (tropospheric only)
    IF (.not. StratBox) THEN
       IF (ALiq.gt.0.0e+0_fp) THEN
          CALL Gamma_HOBr_CLD(rLiq, denAir, 3, TK, clConc, brConc, &
                              hso3Conc, so3Conc, hConc_LCl, GAM_HOBr, r_gp)
          XSTKCF = GAM_HOBr
          kISum = kISum + Arsl1K(ALiq, rLiq, denAir, XStkCf, XTemp, XSqM)*r_gp
       ENDIF
       IF (AIce.gt.0.0e+0_fp) THEN
          CALL Gamma_HOBr_CLD(rIce, denAir, 3, TK, clConc, brConc, &
                              hso3Conc, so3Conc, hConc_ICl, GAM_HOBr, r_gp)
          XSTKCF = GAM_HOBr
          kISum = kISum + Arsl1K(AIce, rIce, denAir, XStkCf, XTemp, XSqM)*r_gp
       ENDIF
    ENDIF

    END FUNCTION HETHOBr_HSO3
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetHOBr_SO3
!
! !DESCRIPTION: Sets the rate of the multiphase reaction HOBr + SO3-- in 
!  sulfate aerosols, on cloud droplets and on PSCs
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETHOBr_SO3( denAir, rLiq, rIce, ALiq, AIce, VAir, TK, &
                          hConc_Sul, hConc_LCl, hConc_ICl, clConc, brConc, &
                          hso3Conc, so3Conc ) &
                          RESULT( kISum )
!
! !INPUT PARAMETERS: 
!
      REAL(fp), INTENT(IN) :: denAir      ! Density of air (#/cm3)
      REAL(fp), INTENT(IN) :: rLiq        ! Radius of liquid cloud droplets (cm)
      REAL(fp), INTENT(IN) :: rIce        ! Radius of ice cloud crystals (cm)
      REAL(fp), INTENT(IN) :: ALiq        ! Area of liquid cloud droplets (cm2/cm3)
      REAL(fp), INTENT(IN) :: AIce        ! Area of ice cloud crystals (cm2/cm3)
      REAL(fp), INTENT(IN) :: VAir        ! Box volume (cm3)
      REAL(fp), INTENT(IN) :: TK          ! Temperature (K)
      REAL(fp), INTENT(IN) :: hConc_Sul   ! Sulfate H+ concentration
      REAL(fp), INTENT(IN) :: hConc_LCl   ! Liquid cloud H+ concentration
      REAL(fp), INTENT(IN) :: hConc_ICl   ! Ice cloud H+ concentration
      REAL(fp), INTENT(IN) :: clConc      ! Chloride concentration (mol/L), qjc
      REAL(fp), INTENT(IN) :: brConc      ! Bromide  concentration (mol/L), qjc
      REAL(fp), INTENT(IN) :: hso3Conc    ! HSO3-    concentration (mol/L), qjc
      REAL(fp), INTENT(IN) :: so3Conc     ! SO3--    concentration (mol/L)
!
! !RETURN VALUE:
!
      REAL(fp)             :: kISum
!
! !REMARKS:
!
! !REVISION HISTORY:
!  15 Nov 2017 - M. Sulprizio  - Generated code based on Qianjie Chen's work
!  01 Dec 2017 - Q.J. Chen     - Updated to account for Cl-, Br-, and HSO3-;
!                                Now calls routine Gamma_HOBr_CLD;
!                                Remove HOBr+S(IV) on sulfate aerosols
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      INTEGER  :: N
      REAL(fp) :: XSTKCF, ADJUSTEDRATE
      Real(fp), Parameter :: XMolWeight=96.9e+0_fp
      Real(fp), Parameter :: XSQM=SQRT(XMolWeight)
      REAL(fp) :: GAM_HOBr, r_gp

      ! Initialize
      kISum        = 0.0_fp
      ADJUSTEDRATE = 0.0_fp
      XSTKCF       = 0.0_fp

      ! Loop over aerosol types
      DO N = 1, NAERO
         XSTKCF = 0e+0_fp
         ! Get the aerosol type
         IF ( N == 8 ) THEN
            ! No HOBr+S(IV) on sulfate aerosols
            XSTKCF = 0e+0_fp
         ELSEIF (N.eq.13) THEN
            ! SSA/STS
            XSTKCF = KHETI_SLA(10)
         ELSEIF (N.eq.14) THEN
            ! Ice/NAT PSC
            IF (NATSURFACE) THEN
               XSTKCF = 0.1e+0_fp ! NAT
            ELSE
               XSTKCF = 0.3e+0_fp ! Ice
            ENDIF
         ELSE
            XSTKCF = 0e+0_fp
         ENDIF

         IF (N.eq.13) THEN
            ! Calculate for stratospheric liquid aerosol
            ! Note that XSTKCF is actually a premultiplying
            ! factor in this case, including c-bar
            ADJUSTEDRATE = XAREA(N) * XSTKCF
         ELSE
            ! Reaction rate for ARSL1K(XAREA(N),XRADI(N),XDENA,XSTKCF,XTEMP,XSQM)
         ENDIF
         
         ! Add to overall reaction rate
         kISum = kISum + ADJUSTEDRATE
      END DO

    ! Hydrolysis on liquid and ice clouds (tropospheric only)
    IF (.not. StratBox) THEN
       IF (ALiq.gt.0.0e+0_fp) THEN
          CALL Gamma_HOBr_CLD(rLiq, denAir, 4, TK, clConc, brConc, &
                              hso3Conc, so3Conc, hConc_LCl, GAM_HOBr, r_gp)
          XSTKCF = GAM_HOBr
          kISum = kISum + Arsl1K(ALiq, rLiq, denAir, XStkCf, XTemp, XSqM)*r_gp
       ENDIF
       IF (AIce.gt.0.0e+0_fp) THEN
          CALL Gamma_HOBr_CLD(rIce, denAir, 4, TK, clConc, brConc, &
                              hso3Conc, so3Conc, hConc_ICl, GAM_HOBr, r_gp)
          XSTKCF = GAM_HOBr
          kISum = kISum + Arsl1K(AIce, rIce, denAir, XStkCf, XTemp, XSqM)*r_gp
       ENDIF
    ENDIF

    END FUNCTION HETHOBr_SO3
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: Gamma_HX_Uptake
!
! !DESCRIPTION: Function GAMMA\_HX\_uptake calculates mass accomidation coef.
!               for uptake of HX (HCl or HBr)
!\\
!\\
! !INTERFACE:
!
      FUNCTION Gamma_HX_Uptake( Radius, n_air, X, T )  RESULT( GAM )  
!
! !OUTPUT PARAMETER:
      ! Reactive uptake coefficient (unitless)
      REAL(fp)                         :: GAM
! !INPUT PARAMETERS:
!
      ! Radius (cm), n_air (#/cm), and X (1 for Cl and 2 for Br)
      REAL(fp), INTENT(IN)             :: Radius, n_air
      INTEGER, INTENT(IN)              :: X
      REAL(fp), INTENT(IN)             :: T
!
! !REVISION HISTORY:
!  24 Sept 2015 - J. Schmidt - Initial version
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
!
      REAL(fp)       :: ab, gd, M_X

      ! 1: Cl-, 2: Br-
      IF (X==1) THEN
         ! This would never be used since HCl uptake is 
         ! handled by ISORROPIA now, xnw 1/25/18
         ab = 4.4e-6_fp * dexp( 2898.0e0_fp / T ) ! ab(RT) = 0.069
      ELSE
         ab = 1.3e-8_fp * dexp( 4290.0e0_fp / T ) ! ab(RT) = 0.021
      ENDIF

      GAM = ab

      END FUNCTION Gamma_HX_Uptake
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
    SUBROUTINE GAMMA_HOBr_CLD( Radius, n_air, X, T, C_Y1, C_Y2, &
                               C_Y3, C_Y4, C_Hp, GAM_HOBr, r_gp )
!
! !USES:
!
      USE PhysConstants,      ONLY : Pi, RStarG
!
! !OUTPUT PARAMETER:
      ! Reactive uptake coefficient (unitless)
      REAL(fp), INTENT(OUT)          :: GAM_HOBr, r_gp
!
! !INPUT PARAMETERS:
!
      ! Radius (cm), n_air (#/cm), and X (1 for Cl and 2 for Br)
      REAL(fp), INTENT(IN)           :: Radius   ! Radius (cm)
      REAL(fp), INTENT(IN)           :: n_air    ! n_air (#/cm)
      INTEGER,  INTENT(IN)           :: X        ! 1=Cl-,2=Br-,3=HSO3-,4=SO3--
      REAL(fp), INTENT(IN)           :: T        ! Temperature (K)
      REAL(fp), INTENT(IN)           :: C_Y1, C_Y2, C_Y3, C_Y4      ! Concentration (mol/L)
      REAL(fp), INTENT(IN)           :: C_Hp     ! Concentration (mol/L)
!
! !REVISION HISTORY:
!  30 Nov 2017 - Q.J. Chen   - Initial version
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
!
      ! Conversion factor from atm to bar
      REAL(fp),  PARAMETER   :: con_atm_bar = 1.0/1.01325

      ! Universal gas consatant [bar/(mol/kg)/K]
      REAL(fp),  PARAMETER   :: con_R     = RStarG*1.0e-2_fp

      !----------
      ! HOCl
      !----------
      ! NOTE: These don't seem to be used anywhere
      REAL(fp),  PARAMETER   :: H_HOCl    = 6.6e2_fp * con_atm_bar !M/bar
      REAL(fp),  PARAMETER   :: H_HOCl_E  = -5900.0
      REAL(fp),  PARAMETER   :: H_HOCl_T  = 298.15
      REAL(fp),  PARAMETER   :: M_HOCl    = 5.246e-2_fp !Hardcoded MW [kg/mol]

      !----------
      ! HOBr
      !----------
      ! Henry's law constant [M/bar], Estimate, but also recommended by IUPAC 
      !REAL(fp),  PARAMETER   :: H_HOBr    = 6.1e3_fp * con_atm_bar
      ! qjc, 11/30/17, used in [Sander, 2015] and [Chen et al., 2017]
      REAL(fp),  PARAMETER   :: H_HOBr    = 1.3e3_fp * con_atm_bar
      REAL(fp),  PARAMETER   :: H_HOBr_E  = -6014.0
      REAL(fp),  PARAMETER   :: H_HOBr_T  = 298.15
      REAL(fp),  PARAMETER   :: M_HOBr    = 9.6911e-2_fp !Hardcoded MW [kg/mol]

      REAL(fp)       :: ab, gd, M_X
      REAL(fp)       :: cavg, H_X
      REAL(fp)       :: gb1, gb2, gb3, gb4, gb_tot
      REAL(fp)       :: k_b1, k_b2, k_b3, k_b4
      REAL(fp)       :: D_l, ybr2

!=================================================================================
!     Change made by lei, 18/12/21
!=================================================================================
!      REAL(fp)       :: l_r1, l_r2, l_r3, l_r4

!!      IF ( X==1 ) THEN
!         ! Reaction rate coefficient for HOBr + Cl- [M-2 s-1]
!         !k_b  = 5.9e+9_fp
!         ! (Liu and Margerum, Environ. Sci. Tech., 2001)
!         k_b1  = 2.3e+10_fp ! (qjc, 12/28/16)
!!      ELSEIF ( X==2 ) THEN
!         ! Reaction rate coefficient for HOBr + Br- [M-2 s-1]
!         k_b2  = 1.6e+10_fp 
!!      ELSEIF ( X==3 ) THEN
!         ! Reaction rate coefficient for HOBr + HSO3- [M-2 s-1]
!         ! (Liu Q. 2000, PhD thesis)
!         k_b3  = 3.2e+9_fp 
!!      ELSEIF ( X==4 ) THEN
!         ! Reaction rate coefficient for HOBr + SO4-- [M-2 s-1]
!         ! (Troy and Margerum, Inorg. Chem., 1991)
!         k_b4  = 5.0e+9_fp 
!!      ENDIF
!
!      ! Liquid phase diffusion coefficient [cm2/s] for HOBr
!      ! (Ammann et al., Atmos. Chem. Phys., 2013)
!      D_l  = 1.4e-5_fp
!
!      H_X = H_HOBr*dexp(-H_HOBr_E*(1.0e0_fp/T - 1.0e0_fp/H_HOBr_T))
!      M_X = M_HOBr
!
!      ! Mass accommodation coefficient
!      ab = 0.6e0_fp
!
!      ! Thermal velocity [cm/s]
!      cavg = dsqrt(8*RStarG*T/(pi*M_X)) *1.0e2_fp
!
!      ! l_r is diffusive length scale [cm]; gb is Bulk reaction coefficient [unitless]
!      l_r1  = dsqrt( D_l / (k_b1 * C_Y1 * C_Hp ) )
!      gb1 = 4.0e0_fp * H_X * con_R * T * l_r1 * k_b1 * C_Y1 * C_Hp / cavg    
!      gb1 = gb1 * REACTODIFF_CORR( Radius, l_r1) 
!
!      l_r2  = dsqrt( D_l / (k_b2 * C_Y2 * C_Hp ) )
!      gb2 = 4.0e0_fp * H_X * con_R * T * l_r2 * k_b2 * C_Y2 * C_Hp / cavg    
!      gb2 = gb2 * REACTODIFF_CORR( Radius, l_r2) 
!
!      l_r3  = dsqrt( D_l / (k_b3 * C_Y3 ) )
!      gb3 = 4.0e0_fp * H_X * con_R * T * l_r3 * k_b3 * C_Y3 / cavg    
!      gb3 = gb3 * REACTODIFF_CORR( Radius, l_r3) 
!
!      l_r4  = dsqrt( D_l / (k_b4 * C_Y4 ) )
!      gb4 = 4.0e0_fp * H_X * con_R * T * l_r4 * k_b4 * C_Y4 / cavg    
!      gb4 = gb4 * REACTODIFF_CORR( Radius, l_r4) 
!
!      gb_tot = gb1 + gb2 + gb3 + gb4
!      
!      ! Reactive uptake coefficient [unitless]
!      GAM_HOBr = 1.0e0_fp / (1.0e0_fp/ab  +  1.0e0_fp/gb_tot)

!      ! Over all reactive uptake coefficient [unitless]
!      GAM_HOBr = 1.0e0_fp / (1.0e0_fp/ab  +  1.0e0_fp/gb_tot)
!
!      ybr2 = 0.41e0*LOG10(C_Y2/C_Y1)+2.25        ! yield of Br2
!      ybr2 = MIN(ybr2, 0.9e0)
!      ybr2 = MAX(ybr2, TINY(1.0e0))
!
!      IF ( X==1 ) THEN
!
!         r_gp = (gb1+gb2)/gb_tot
!
!         IF (C_Y2/C_Y1>5.e-4) THEN
!            r_gp = 0.1e0 * r_gp
!         ELSE
!            r_gp = r_gp * (1.e0 - ybr2)
!         ENDIF
!
!      ELSEIF ( X==2 ) THEN
!
!         r_gp = (gb1+gb2)/gb_tot
!
!         IF (C_Y2/C_Y1>5.e-4) THEN
!            r_gp = 0.9e0 * r_gp
!         ELSE
!            r_gp = r_gp * ybr2
!         ENDIF
!
!      ELSEIF ( X==3 ) THEN
!
!         r_gp = gb3/gb_tot
!
!      ELSEIF ( X==4 ) THEN
!
!         r_gp = gb4/gb_tot
!
!      ENDIF
!==================================================================================
!==================================================================================

      REAL(fp)       :: r1, r2, r3, r4, l_r_tot, r_tot

!      IF ( X==1 ) THEN
         ! Reaction rate coefficient for HOBr + Cl- [M-2 s-1]
         !k_b  = 5.9e+9_fp
         ! (Liu and Margerum, Environ. Sci. Tech., 2001)
         k_b1  = 2.3e+10_fp ! (qjc, 12/28/16)
!      ELSEIF ( X==2 ) THEN
         ! Reaction rate coefficient for HOBr + Br- [M-2 s-1]
         k_b2  = 1.6e+10_fp
!      ELSEIF ( X==3 ) THEN
         ! Reaction rate coefficient for HOBr + HSO3- [M-1 s-1]
         ! (Liu Q., 2000, PhD thesis)
         k_b3  = 3.2e+9_fp
!      ELSEIF ( X==4 ) THEN
         ! Reaction rate coefficient for HOBr + SO3-- [M-1 s-1]
         ! (Troy and Margerum, Inorg. Chem., 1991)
         k_b4  = 5.0e+9_fp
!      ENDIF

      ! Liquid phase diffusion coefficient [cm2/s] for HOBr
      ! (Ammann et al., Atmos. Chem. Phys., 2013)
      D_l  = 1.4e-5_fp

      H_X = H_HOBr*dexp(-H_HOBr_E*(1.0e0_fp/T - 1.0e0_fp/H_HOBr_T))
      M_X = M_HOBr

      ! Mass accommodation coefficient
      ab = 0.6e0_fp

      ! Thermal velocity [cm/s]
      cavg = dsqrt(8*RStarG*T/(pi*M_X)) *1.0e2_fp

      ! r is the first order loss rate coefficient
      r1  = k_b1 * C_Y1 * C_Hp
      r2  = k_b2 * C_Y2 * C_Hp
      r3  = k_b3 * C_Y3
      r4  = k_b4 * C_Y4

      ! Make change here, lei, 18/12/18
      r_tot    = r1 + r2 + r3 + r4
      ! l_r is diffusive length scale [cm]
      ! gb is Bulk reaction coefficient [unitless]
      l_r_tot  = dsqrt( D_l / r_tot )
      gb_tot = 4.0e0_fp * H_X * con_R * T * l_r_tot * r_tot / cavg
      gb_tot = gb_tot * REACTODIFF_CORR( Radius, l_r_tot)

      ! Overall reactive uptake coefficient [unitless]
      ! This is used to compute the overall loss rate of HOBr
      GAM_HOBr = 1.0e0_fp / (1.0e0_fp/ab  +  1.0e0_fp/gb_tot)

      ! Now we need to alloacte the overall loss rate of HOBr
      ! to different pathways. This is done by assuming that
      ! the weight (r_gp) is proportional to the 1st loss rate 
      ! coefficient in the condensed phase (ri)

      ! Br2 yield, based on Fickert et al. 1999
      ! Condier HOBr + Cl- and Br- together
      ybr2 = 0.41e0*LOG10(C_Y2/C_Y1)+2.25
      ybr2 = MIN(ybr2, 0.9e0)
      ybr2 = MAX(ybr2, TINY(1.0e0))

      IF ( X==1 ) THEN

         ! Production rate of BrCl
         ! same as loss rate of HOBr due to HOBr + H+ + Cl-
         r_gp = (r1+r2) / r_tot

         IF (C_Y2/C_Y1>5.e-4) THEN
            r_gp = 0.1e0 * r_gp
         ELSE
            r_gp = r_gp * (1.e0 - ybr2)
         ENDIF

      ELSEIF ( X==2 ) THEN
         ! Production of Br2
         ! same as loss rate of HOBr due to HOBr + H+ + Br-
         r_gp = (r1 + r2) / r_tot

         IF (C_Y2/C_Y1>5.e-4) THEN
            r_gp = 0.9e0 * r_gp
         ELSE
            r_gp = r_gp * ybr2
         ENDIF

      ELSEIF ( X==3 ) THEN
         ! Loss rate of HOBr due to HOBr + HSO3-
         r_gp = r3 / r_tot

      ELSEIF ( X==4 ) THEN
         ! Loss rate of HOBr due to HOBr + SO3--
         r_gp = r4 / r_tot

      ENDIF

    END SUBROUTINE GAMMA_HOBr_CLD

!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
    SUBROUTINE GAMMA_HOBr_AER( Radius, n_air, X, T, C_Y1, C_Y2, &
                               C_Hp, GAM_HOBr, r_gp )
!
! !USES:
!
      USE PhysConstants,      ONLY : Pi, RStarG
!
! !OUTPUT PARAMETER:
      ! Reactive uptake coefficient (unitless)
      REAL(fp), INTENT(OUT)          :: GAM_HOBr, r_gp
!
! !INPUT PARAMETERS:
!
      ! Radius (cm), n_air (#/cm), and X (1 for Cl and 2 for Br)
      REAL(fp), INTENT(IN)           :: Radius   ! Radius (cm)
      REAL(fp), INTENT(IN)           :: n_air    ! n_air (#/cm)
      INTEGER,  INTENT(IN)           :: X        ! 1=Cl-,2=Br-,3=HSO3-,4=SO3--
      REAL(fp), INTENT(IN)           :: T        ! Temperature (K)
      REAL(fp), INTENT(IN)           :: C_Y1, C_Y2      ! Concentration (mol/L)
      REAL(fp), INTENT(IN)           :: C_Hp     ! Concentration (mol/L)
!
! !REVISION HISTORY:
!  30 Nov 2017 - Q.J. Chen   - Initial version
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
!
      ! Conversion factor from atm to bar
      REAL(fp),  PARAMETER   :: con_atm_bar = 1.0/1.01325

      ! Universal gas consatant [bar/(mol/kg)/K]
      REAL(fp),  PARAMETER   :: con_R     = RStarG*1.0e-2_fp 

      !----------
      ! HOCl
      !----------
      ! NOTE: These don't seem to be used anywhere
      REAL(fp),  PARAMETER   :: H_HOCl    = 6.6e2_fp * con_atm_bar !M/bar
      REAL(fp),  PARAMETER   :: H_HOCl_E  = -5900.0
      REAL(fp),  PARAMETER   :: H_HOCl_T  = 298.15
      REAL(fp),  PARAMETER   :: M_HOCl    = 5.246e-2_fp !Hardcoded MW [kg/mol]

      !----------
      ! HOBr
      !----------
      ! Henry's law constant [M/bar], Estimate, but also recommended by IUPAC 
      !REAL(fp),  PARAMETER   :: H_HOBr    = 6.1e3_fp * con_atm_bar
      ! qjc, 11/30/17, used in [Sander, 2015] and [Chen et al., 2017]
      REAL(fp),  PARAMETER   :: H_HOBr    = 1.3e3_fp * con_atm_bar
      REAL(fp),  PARAMETER   :: H_HOBr_E  = -6014.0
      REAL(fp),  PARAMETER   :: H_HOBr_T  = 298.15
      REAL(fp),  PARAMETER   :: M_HOBr    = 9.6911e-2_fp !Hardcoded MW [kg/mol]

      REAL(fp)       :: ab, gd, M_X
      REAL(fp)       :: cavg, H_X
      REAL(fp)       :: gb1, gb2, gb_tot
      REAL(fp)       :: k_b1, k_b2
      REAL(fp)       :: D_l, ybr2
      REAL(fp)       :: l_r1, l_r2

      ! Reaction rate coefficient for HOBr + Cl- [M-2 s-1]
      !k_b  = 5.9e+9_fp
      ! (Liu and Margerum, Environ. Sci. Tech., 2001)
      k_b1  = 2.3e+10_fp ! (qjc, 12/28/16)
      ! Reaction rate coefficient for HOBr + Br- [M-2 s-1]
      k_b2  = 1.6e+10_fp 

      ! Liquid phase diffusion coefficient [cm2/s] for HOBr
      ! (Ammann et al., Atmos. Chem. Phys., 2013)
      D_l  = 1.4e-5_fp

      H_X = H_HOBr*dexp(-H_HOBr_E*(1.0e0_fp/T - 1.0e0_fp/H_HOBr_T))
      M_X = M_HOBr

      ! Mass accommodation coefficient
      ab = 0.6e0_fp

      ! Thermal velocity [cm/s]
      cavg = dsqrt(8*RStarG*T/(pi*M_X)) *1.0e2_fp

      ! l_r is diffusive length scale [cm]; gb is Bulk reaction coefficient [unitless]
      l_r1  = dsqrt( D_l / (k_b1 * C_Y1 * C_Hp ) )
      gb1 = 4.0e0_fp * H_X * con_R * T * l_r1 * k_b1 * C_Y1 * C_Hp / cavg    
      gb1 = gb1 * REACTODIFF_CORR( Radius, l_r1) 

      l_r2  = dsqrt( D_l / (k_b2 * C_Y2 * C_Hp ) )
      gb2 = 4.0e0_fp * H_X * con_R * T * l_r2 * k_b2 * C_Y2 * C_Hp / cavg    
      gb2 = gb2 * REACTODIFF_CORR( Radius, l_r2) 

      gb_tot = gb1 + gb2
      
      ! Reactive uptake coefficient [unitless]
      GAM_HOBr = 1.0e0_fp / (1.0e0_fp/ab  +  1.0e0_fp/gb_tot)
      
      ybr2 = 0.41e0*LOG10(C_Y2/C_Y1)+2.25        ! yield of Br2
      ybr2 = MIN(ybr2, 0.9e0)
      ybr2 = MAX(ybr2, TINY(1.0e0))

      IF ( X==1 ) THEN

         r_gp = (gb1+gb2)/gb_tot

         IF (C_Y2/C_Y1>5.e-4) THEN
            r_gp = 0.1e0 * r_gp
         ELSE
            r_gp = r_gp * (1.e0 - ybr2)
         ENDIF

      ELSEIF ( X==2 ) THEN

         r_gp = (gb1+gb2)/gb_tot

         IF (C_Y2/C_Y1>5.e-4) THEN
            r_gp = 0.9e0 * r_gp
         ELSE
            r_gp = r_gp * ybr2
         ENDIF

      ENDIF

    END SUBROUTINE GAMMA_HOBr_AER
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: Gamma_ClNO3_AER
!
! !DESCRIPTION: Function GAMMA\_ClNO3\_AER calculates reactive uptake coef.
!               for ClNO3 + Cl-/Br-
!\\
!\\
! !INTERFACE:
!
    SUBROUTINE GAMMA_ClNO3_AER( Radius, n_air, X, T, M, C_Y1, C_Y2, &
                                GAM_ClNO3, r_gp ) 
!
! !USES:
!
      USE PhysConstants,      ONLY : Pi, RStarG
!
! !OUTPUT PARAMETER:
      ! Reactive uptake coefficient (unitless)
      REAL(fp)                         :: GAM_ClNO3, r_gp
! !INPUT PARAMETERS:
!
      ! Radius (cm), n_air (#/cm), and X (1 for Cl and 2 for Br)
      REAL(fp), INTENT(IN)           :: Radius   ! Radius (cm)
      REAL(fp), INTENT(IN)           :: n_air    ! n_air (#/cm)
      INTEGER,  INTENT(IN)           :: X        ! 1=Cl-,2=Br-,3=hydrosis
      REAL(fp), INTENT(IN)           :: T        ! Temperature (K)
      REAL(fp), INTENT(IN)           :: C_Y1, C_Y2      ! Concentration (mol/L)
      INTEGER,  INTENT(IN)           :: M        ! 1=fine, 2= coarse, 3=cloud
!
! !REVISION HISTORY:
!  25 Jan 2018 - X. Wang - Initial version
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
!
      ! Universal gas consatant [bar/(mol/kg)/K]
      REAL(fp),  PARAMETER   :: con_R     = RStarG*1.0e-2_fp !bar/(mol/kg)/K
      ! ClONO2 MW [kg/mol]
      REAL(fp),  PARAMETER   :: M_ClNO3  = 9.746e-2_fp

      REAL(fp)       :: ab, M_X, fCl
      REAL(fp)       :: cavg, D_l
      REAL(fp)       :: gb1, gb2, gb_tot
      

      M_X = M_ClNO3
      ! Mass accommodation coefficient
      ab = 0.108e0_fp

      ! Calculate gb1 for ClNO3 + Cl-

      ! Following [Deiber et al., 2004], gamma is not significantly different
      ! from ClNO3 + H2O (gamma = 0.0244) independent of Cl- concentration, 
      ! but Cl2 rather than HOCl formed. gb2 can be calculated reversely from
      ! gamma and ab:
      gb1 = 0.032e0_fp

      ! Calculate gb2 for ClNO3 + Br-

      cavg = dsqrt(8.0e+0_fp*RStarG*T/(Pi*M_X)) *1.0e2_fp ! thermal velocity (cm/s)

      D_l  = 5.0e-6_fp !cm2 s-1. 
      gb2   = 4.0e0_fp * con_R * T * 1.0e6_fp * dsqrt(C_Y2*D_l) / cavg ! H*sqrt(kb)=10^6 (M/s)^½ s-1

      gb_tot = gb1 + gb2
      
      GAM_ClNO3 = 1.0e0_fp / (1.0e0_fp/ab  +  1.0e0_fp/gb_tot)

      GAM_ClNO3 = max(GAM_ClNO3, 0.024e0_fp)

      IF (M .EQ. 1) THEN
         fCl = SPC_fCl / (SPC_fCl + SPC_NIT + SPC_SO4)
      ELSEIF (M .EQ. 2) THEN
         fCl = 1.0e0_fp
      ELSE
         fCl = 0.0e0_fp
      ENDIF    

      IF ( X==1 ) THEN
         r_gp = (gb1 / gb_tot) * fCl
      ELSEIF ( X==2 ) THEN
         r_gp = gb2 / gb_tot
      ELSEIF ( X==3 ) THEN
         r_gp = (gb1 / gb_tot) * (1.0e0_fp-fCl)
      ENDIF

    END SUBROUTINE GAMMA_ClNO3_AER
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: COTH
!
! !DESCRIPTION: COTH (Hyperbolic cotangent)
! !             coth(x) = cosh(x)/sinh(x) = (1 + exp(-2x))/(1 - exp(-2x))
!
!\\
!\\
! !INTERFACE:
!
      REAL(fp) FUNCTION COTH( X) 
! 
! !INPUT PARAMETERS:
!
      REAL(fp),         INTENT(IN)  :: X           ! The argument
!
! !REVISION HISTORY:
!  24 Sept 2015 - J. Schmidt - Initial version
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!

      REAL(fp)                 :: exp_temp

      exp_temp = dexp(-2.0e0_fp*X)
      COTH = (1.0e0_fp + exp_temp)/(1.0e0_fp - exp_temp)

      RETURN

      END FUNCTION COTH
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: REACTODIFF_CORR
!
! !DESCRIPTION: REACTODIFF_CORR 
! !    Correction =  COTH( x ) - ( 1/x )
! !             x = radius / l
! !    Correction approaches 1 as x becomes large, corr(x>1000)~1
! !    Correction approaches x/3 as x goes towards 0
!
!\\
!\\
! !INTERFACE:
! 
      REAL(fp) FUNCTION REACTODIFF_CORR( radius, l) 
! 
! !INPUT PARAMETERS:
!
      REAL(fp),         INTENT(IN)  :: radius, l           ! [cm] and [cm]
!
! !REVISION HISTORY:
!  14 Oct 2013 - J. Schmidt - Initial version
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!

      REAL(fp)                 :: x
 
      x = radius / l
 
      IF (x<0.0e0_fp) THEN
         PRINT *, 'ERROR x<0, particle radius or C_Y is neg!'
      ELSEIF (x>1.0e3_fp) THEN
         REACTODIFF_CORR = 1.0e0_fp
      ELSEIF (x<1.0e-1_fp) THEN
         REACTODIFF_CORR = x/3.0e0_fp
      ELSE
         REACTODIFF_CORR = COTH(x) - (1.0e0_fp/x)
      ENDIF


      RETURN

      END FUNCTION REACTODIFF_CORR
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetBrNO3_JS
!
! !DESCRIPTION: Sets the hydrolysis rate for BrNO3 using Johan Schmidt's
!  updated code.
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETBrNO3_JS( denAir, rLiq, rIce, ALiq, AIce, TK ) RESULT( HET_BrNO3 )
!
! !INPUT PARAMETERS: 
!
      REAL(fp), INTENT(IN) :: denAir      ! Density of air (#/cm3)
      REAL(fp), INTENT(IN) :: rLiq        ! Radius of liquid cloud droplets (cm)
      REAL(fp), INTENT(IN) :: rIce        ! Radius of ice cloud crystals (cm)
      REAL(fp), INTENT(IN) :: ALiq        ! Area of liquid cloud droplets (cm2/cm3)
      REAL(fp), INTENT(IN) :: AIce        ! Area of ice cloud crystals (cm2/cm3)
      REAL(fp), INTENT(IN) :: TK          ! Temperature (K)
!
! !RETURN VALUE:
!
      REAL(fp)             :: HET_BrNO3
!
! !REMARKS:
!
! !REVISION HISTORY:
!  29 Mar 2016 - R. Yantosca - Added ProTeX header
!  01 Apr 2016 - R. Yantosca - Define N, XSTKCF, ADJUSTEDRATE locally
!  01 Apr 2016 - R. Yantosca - Replace KII_KI with DO_EDUCT local variable
!  16 Dec 2016 - S. D. Eastham - Updated code based on Johan Schmidt's work
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      LOGICAL  :: DO_EDUCT
      INTEGER  :: N
      REAL(fp) :: XSTKCF, ADJUSTEDRATE
      Real(fp), Parameter :: XMolWeight=142.0e+0_fp
      Real(fp), Parameter :: XSQM=SQRT(XMolWeight)

      ! Initialize
      HET_BrNO3    = 0.0_fp
      ADJUSTEDRATE = 0.0_fp
      XSTKCF       = 0.0_fp

      ! Only apply PSC rate adjustment if at high altitude
      DO_EDUCT     = STRATBOX

      ! Loop over aerosol types
      DO N = 1, NAERO
         XSTKCF = 0e+0_fp
         ! Get the aerosol type
         IF ( N == 8 ) THEN
            ! sulfate aerosol
            XSTKCF = 0.02e+0_fp
         ELSEIF ( (N == 11) .OR. ( N == 12) ) THEN
            ! 2 modes of sea-salt
            XSTKCF = 0.02e+0_fp
         ELSEIF ( N == 13 ) THEN
            ! SSA/STS
            XSTKCF = KHETI_SLA(6)
         ELSEIF ( N == 14 ) THEN 
            ! Ice/NAT PSC
            IF (NATSURFACE) THEN 
               XSTKCF = 0.001e+0_fp
            ELSE
               XSTKCF = 0.3e+0_fp
            ENDIF
         ELSE
            XSTKCF = 0e+0_fp
         ENDIF

         IF (N.eq.13) THEN
            ! Calculate for stratospheric liquid aerosol
            ! Note that XSTKCF is actually a premultiplying
            ! factor in this case, including c-bar
            ADJUSTEDRATE = XAREA(N) * XSTKCF
         ELSE
            ! Reaction rate for surface of aerosol
            ADJUSTEDRATE=ARSL1K(XAREA(N),XRADI(N),XDENA,XSTKCF,XTEMP,XSQM)
         ENDIF
         
         ! Add to overall reaction rate
         HET_BrNO3 = HET_BrNO3 + ADJUSTEDRATE
      END DO

    ! Hydrolysis on liquid and ice clouds (tropospheric only)
    IF (.not. StratBox) THEN
       HET_BrNO3 = HET_BrNO3 + Cld1K_XNO3(denAir,TK,rLiq,rIce,ALiq,AIce,XMolWeight,2.0E-2_fp)
    ENDIF

    END FUNCTION HETBrNO3_JS
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetClNO3_HCl
!
! !DESCRIPTION: Sets the heterogenous chemistry rate for ClNO3(g) + HCl(l,s)
! in polar stratospheric clouds and on tropospheric sulfate.
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETClNO3_HCl( A,B ) RESULT( kISum )
!
! !INPUT PARAMETERS:
!
      ! Rate coefficients
      REAL(fp), INTENT(IN) :: A, B
!
! !RETURN VALUE:
!
      REAL(fp)             :: kISum
!
! !REMARKS:
!  This routine is only activated for UCX-based mechanisms.
!
! !REVISION HISTORY:
!  29 Jan 2016 - M. Sulprizio- Initial version, adapted from code previously
!                              in calcrate.F
!  29 Mar 2016 - R. Yantosca - Added ProTeX header
!  01 Apr 2016 - R. Yantosca - Define N, XSTKCF, ADJUSTEDRATE locally
!  01 Apr 2016 - R. Yantosca - Replace KII_KI with DO_EDUCT local variable
!  04 May 2016 - M. Sulprizio- Add fixes for setting rate if not a STRATBOX
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      LOGICAL  :: DO_EDUCT
      INTEGER  :: N
      REAL(fp) :: XSTKCF, ADJUSTEDRATE
      Real(fp) :: XSQM

      ! Initialize
      kISum          = 0.0_fp
      ADJUSTEDRATE   = 0.0_fp
      XSTKCF         = 0.0_fp
      XSQM=SQRT(A)

      ! Loop over aerosol types
      DO N = 1, NAERO

         ! Assume zero unless proven otherwise
         XSTKCF = 0e+0_fp

!         IF (N.eq.8) THEN
!            XSTKCF = 0.1e-4_fp ! Sulfate
!         ELSEIF ( STRATBOX ) THEN
!            IF (N.eq.13) THEN
	 ! restore limitation to stratosphere
         IF  ( STRATBOX ) THEN
            IF (N.eq.8) THEN
               XSTKCF = 0.1e-4_fp ! Sulfate
            ELSEIF (N.eq.13) THEN
               XSTKCF = KHETI_SLA(4)
            ELSEIF (N.eq.14) THEN
               IF (NATSURFACE) THEN
                  XSTKCF = 0.2e+0_fp ! NAT
               ELSE
                  XSTKCF = 0.3e+0_fp ! Ice
               ENDIF
            ENDIF
         ENDIF

         IF (STRATBOX.and.(N.eq.13)) THEN
            ! Calculate for stratospheric liquid aerosol
            ! Note that XSTKCF is actually a premultiplying
            ! factor in this case, including c-bar
            ADJUSTEDRATE = XAREA(N) * XSTKCF
         ELSE IF (XSTKCF .GT. 0.0e+0_fp) THEN
            ! Reaction rate for surface of aerosol
            ADJUSTEDRATE=ARSL1K(XAREA(N),XRADI(N),XDENA,XSTKCF,XTEMP, &
                               XSQM)
         ENDIF

         ! Add to overall reaction rate
         kISum = kISum + ADJUSTEDRATE

      END DO

    END FUNCTION HETClNO3_HCl
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetBrNO3_HCl
!
! !DESCRIPTION: Set heterogenous chemistry rate for BrNO3(g) + HCl(l,s)
!  in polar stratospheric clouds and on tropospheric sulfate.
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETBrNO3_HCl( A, B ) RESULT( kISum )
!
! !INPUT PARAMETERS: 
!
      ! Rate coefficients
      REAL(fp), INTENT(IN) :: A, B
!
! !RETURN VALUE: 
!
      REAL(fp)             :: kISum
!
! !REMARKS:
!
! !REVISION HISTORY:
!  29 Jan 2016 - M. Sulprizio- Initial version, adapted from code previously
!                              in calcrate.F
!  29 Mar 2016 - R. Yantosca - Added ProTeX header
!  01 Apr 2016 - R. Yantosca - Define N, XSTKCF, ADJUSTEDRATE locally
!  01 Apr 2016 - R. Yantosca - Replace KII_KI with DO_EDUCT local variable
!  04 May 2016 - M. Sulprizio- Add fixes for setting rate if not a STRATBOX
!  24 Dec 2016 - S. D. Eastham - Extended into the troposphere
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      LOGICAL  :: DO_EDUCT
      INTEGER  :: N
      REAL(fp) :: XSTKCF, ADJUSTEDRATE

      ! Initialize
      kISum         = 0.0_fp
      ADJUSTEDRATE  = 0.0_fp
      XSTKCF        = 0.0_fp

      ! Loop over aerosol types
      DO N = 1, NAERO

         ! Default to zero
         XSTKCF = 0.0e+0_fp
	 ! restore limitation to stratosphere
	 IF ( STRATBOX ) THEN
	    IF (N.eq.8) THEN
               XSTKCF = 0.9e+0_fp ! Sulfate
            ELSEIF (N.eq.13) THEN
               XSTKCF = KHETI_SLA(7)
            ELSEIF (N.eq.14) THEN
               IF (NATSURFACE) THEN
                  XSTKCF = 0.3e+0_fp ! NAT
               ELSE
                  XSTKCF = 0.3e+0_fp ! Ice
               ENDIF
            ENDIF
         ENDIF

         IF (XStkCf.gt.0.0e+0_fp) THEN
            IF (N.eq.13) THEN
               ! Calculate for stratospheric liquid aerosol
               ! Note that XSTKCF is actually a premultiplying
               ! factor in this case, including c-bar
               ADJUSTEDRATE = XAREA(N) * XSTKCF
            ELSE
               ! Reaction rate for surface of aerosol
               ADJUSTEDRATE=ARSL1K(XAREA(N),XRADI(N),XDENA,XSTKCF,XTEMP, &
                                  (A**0.5_FP))
            ENDIF

            ! Add to overall reaction rate
            kISum = kISum + ADJUSTEDRATE
         ENDIF

      END DO

    END FUNCTION HETBrNO3_HCl
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetHOCl_HCl
!
! !DESCRIPTION: Set heterogenous chemistry rate for HOCl(g) + HCl(l,s)
!  in polar stratospheric clouds and on sulfate aerosol.
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETHOCl_HCl( A, B ) RESULT( kISum )
!
! !INPUT PARAMETERS: 
!
      ! Rate coefficients
      REAL(fp), INTENT(IN) :: A, B
!
! !RETURN VALUE:
!
      REAL(fp)             :: kISum
!
! !REMARKS:
!
! !REVISION HISTORY:
!  29 Jan 2016 - M. Sulprizio- Initial version, adapted from code previously
!                              in calcrate.F
!  29 Mar 2016 - R. Yantosca - Added ProTeX header
!  01 Apr 2016 - R. Yantosca - Define N, XSTKCF, ADJUSTEDRATE locally
!  01 Apr 2016 - R. Yantosca - Replace KII_KI with DO_EDUCT local variable
!  04 May 2016 - M. Sulprizio- Add fixes for setting rate if not a STRATBOX
!  22 Dec 2016 - S. D. Eastham - Now active for non-UCX mechanisms
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      INTEGER  :: N
      REAL(fp) :: XSTKCF, ADJUSTEDRATE

      ! Initialize
      kISum         = 0.0_fp
      ADJUSTEDRATE  = 0.0_fp
      XSTKCF        = 0.0_fp

      ! Loop over aerosol types
      DO N = 1, NAERO

         XSTKCF        = 0.0_fp

         ! Only consider PSC reactions in strat
#if defined( UCX )
         IF (STRATBOX) THEN
	    ! restore limitation to stratosphere
	    IF (N.eq.8) THEN
	       XSTKCF = 0.8e+0_fp ! Sulfate
            ELSEIF (N.eq.13) THEN
               XSTKCF = KHETI_SLA(8)
            ELSEIF (N.eq.14) THEN
               IF (NATSURFACE) THEN
                  XSTKCF = 0.1e+0_fp ! NAT
               ELSE
                  XSTKCF = 0.2e+0_fp ! Ice
               ENDIF
            ENDIF
         ENDIF
#endif

         IF (XStkCf.gt.0.0e+0_fp) THEN
            IF (N.eq.13) THEN
               ! Calculate for stratospheric liquid aerosol
               ! Note that XSTKCF is actually a premultiplying
               ! factor in this case, including c-bar
               ADJUSTEDRATE = XAREA(N) * XSTKCF
            ELSE
               ! Reaction rate for surface of aerosol
               ADJUSTEDRATE=ARSL1K(XAREA(N),XRADI(N),XDENA,XSTKCF,XTEMP, &
                                  (A**0.5_FP))
            ENDIF

            ! Add to overall reaction rate
            kISum = kISum + AdjustedRate

         ENDIF

      END DO

    END FUNCTION HETHOCl_HCl
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetHOCl_HBr
!
! !DESCRIPTION: Set heterogenous chemistry rate for HOCl(g) + HBr(l,s)
!  in polar stratospheric clouds and on sulfate aerosol.
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETHOCl_HBr( A, B ) RESULT( kISum )
!
! !INPUT PARAMETERS: 
!
      ! Rate coefficients
      REAL(fp), INTENT(IN) :: A, B
!
! !RETURN VALUE:
!
      REAL(fp)             :: kISum
!
! !REMARKS:
!
! !REVISION HISTORY:
!  29 Jan 2016 - M. Sulprizio- Initial version, adapted from code previously
!                              in calcrate.F
!  29 Mar 2016 - R. Yantosca - Added ProTeX header
!  01 Apr 2016 - R. Yantosca - Define N, XSTKCF, ADJUSTEDRATE locally
!  01 Apr 2016 - R. Yantosca - Replace KII_KI with DO_EDUCT local variable
!  04 May 2016 - M. Sulprizio- Add fixes for setting rate if not a STRATBOX
!  22 Dec 2016 - S. D. Eastham - Now active for non-UCX mechanisms
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      INTEGER  :: N
      REAL(fp) :: XSTKCF, ADJUSTEDRATE

      ! Initialize
      kISum         = 0.0_fp
      ADJUSTEDRATE  = 0.0_fp
      XSTKCF        = 0.0_fp

      ! Loop over aerosol types
      DO N = 1, NAERO

         XSTKCF        = 0.0_fp
         ! Only consider PSC reactions in strat
#if defined( UCX )
         IF (STRATBOX) THEN
	 ! restore limitation to stratosphere
	    IF (N.eq.8) THEN
 	       XSTKCF = 0.8e+0_fp ! Sulfate
            ELSEIF (N.eq.13) THEN
               XSTKCF = KHETI_SLA(9)
            ELSEIF (N.eq.14) THEN
               IF (NATSURFACE) THEN
                  XSTKCF = 0.3e+0_fp ! NAT
               ELSE
                  XSTKCF = 0.3e+0_fp ! Ice
               ENDIF
            ENDIF
         ENDIF
#endif

         IF (XStkCf.gt.0.0e+0_fp) THEN
            IF (N.eq.13) THEN
               ! Calculate for stratospheric liquid aerosol
               ! Note that XSTKCF is actually a premultiplying
               ! factor in this case, including c-bar
               ADJUSTEDRATE = XAREA(N) * XSTKCF
            ELSE
               ! Reaction rate for surface of aerosol
               ADJUSTEDRATE=ARSL1K(XAREA(N),XRADI(N),XDENA,XSTKCF,XTEMP, &
                                  (A**0.5_FP))
            ENDIF

            ! Add to overall reaction rate
            kISum = kISum + AdjustedRate

         ENDIF

      END DO

    END FUNCTION HETHOCl_HBr
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HetHOCl_SS
!
! !DESCRIPTION: Set heterogenous chemistry rate for HOCl on Cl- aerosols
!\\
!\\
! !INTERFACE:
!
    FUNCTION HETHOCl_SS(denAir, rAer, AAer, alkAer, TK, hconc, clconc) RESULT( kISum )
!
! !INPUT PARAMETERS: 
!
      REAL(fp), INTENT(IN) :: denAir      ! Density of air (#/cm3)
      REAL(fp), INTENT(IN) :: rAer        ! Radius of aerosol (cm)
      REAL(fp), INTENT(IN) :: AAer        ! Area of aerosol (cm2/cm3)
      REAL(fp), INTENT(IN) :: alkAer      ! Aerosol alkalinity (eqn)
      REAL(fp), INTENT(IN) :: TK          ! Temperature (K)
      REAL(fp), INTENT(IN) :: hconc       ! H+ (M)
      REAL(fp), INTENT(IN) :: clconc       ! Cl- (M)
!
! !RETURN VALUE:
!
      REAL(fp)             :: kISum
! !REMARKS:
!
! !REVISION HISTORY:
!  25 Jan 2018 - X. Wang - Initial vesion
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      REAL(fp) :: XSTKCF
      Real(fp), Parameter :: XMolWeight=52.45e+0_fp
      Real(fp), Parameter :: XSQM=SQRT(XMolWeight)
!
! !DEFINED PARAMETERS:
!
      ! Initialize
      kISum        = 0.0_fp

      ! Reaction can only proceed on acidic aerosol
      IF (alkAer > 0.05e+0_fp) THEN
         XStkCf = 0.0e+0_fp
      ELSE
         XStkCf = GAMMA_HOCl(rAer, denAir, TK, hconc, clconc)
      ENDIF

      ! Reaction rate
      kISum = ARSL1K( AAer, rAer, denAir, XSTKCF, XTEMP, XSQM )

    END FUNCTION HETHOCl_SS
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: N2O5
!
! !DESCRIPTION: Internal function N2O5 computes the GAMMA sticking factor
!  for N2O5 hydrolysis. (mje, bmy, 8/7/03)
!\\
!\\
! !INTERFACE:
!
    FUNCTION N2O5( AEROTYPE, TEMP, RH ) RESULT( GAMMA )
!
! !INPUT PARAMETERS: 
!
      INTEGER,   INTENT(IN) :: AEROTYPE  ! Denoting aerosol type (cf FAST_JX)
      REAL(fp),  INTENT(IN) :: TEMP      ! Temperature [K]
      REAL(fp),  INTENT(IN) :: RH        ! Relative humidity [1]
!
! !RETURN VALUE:
!
      REAL(fp)              :: GAMMA

!
! !REMARKS:
!  Taken from the old SMVGEAR function calcrate.F.
!
! !REVISION HISTORY:
!  29 Mar 2016 - R. Yantosca - Added ProTeX headers
!  15 Jun 2017 - M. Sulprizio- Move conversion of RH from fraction to % to
!                              SET_HET above
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      ! Local variables
      REAL(fp) :: RH_P, FACT, TTEMP

      !=================================================================
      ! N2O5 begins here!
      !=================================================================

      ! RH percent max = 100%
      RH_P  = MIN( RH, 100e0_fp )

      ! Default value
      GAMMA = 0.01e+0_fp

      ! Special handling for various aerosols
      SELECT CASE ( AEROTYPE )

         !----------------
         ! Dust 
         !----------------
         CASE ( 1, 2, 3, 4, 5, 6, 7 )      
                                
            ! Based on unpublished Crowley work
            GAMMA = 0.01e+0_fp

         !----------------
         ! Sulfate
         !----------------
         CASE ( 8 )     
            ! This is not used when considering Cl-, xnw       
            !===========================================================
            ! RH dependence from Kane et al., Heterogenous uptake of 
            ! gaseous N2O5 by (NH4)2SO4, NH4HSO4 and H2SO4 aerosols
            ! J. Phys. Chem. A , 2001, 105, 6465-6470 
            !===========================================================
            ! No RH dependence above 50.0% (lzh, 10/26/2011)
            ! According to Bertram and Thornton, ACP, 9, 8351-8363, 2009
            RH_P  = MIN( RH_P, 50e+0_fp )

            GAMMA = 2.79e-4_fp + RH_P*(  1.30e-4_fp +    &
                              RH_P*( -3.43e-6_fp +       &
                              RH_P*(  7.52e-8_fp ) ) )

            !===========================================================
            ! Temperature dependence factor (Cox et al, Cambridge UK) 
            ! is of the form:
            !
            !          10^( LOG10( G294 ) - 0.04 * ( TTEMP - 294 ) )
            ! FACT = -------------------------------------------------
            !                     10^( LOG10( G294 ) )
            !
            ! Where G294 = 1e-2 and TTEMP is MAX( TEMP, 282 ).
            ! 
            ! For computational speed, replace LOG10( 1e-2 ) with -2
            ! and replace 10^( LOG10( G294 ) ) with G294 
            !===========================================================
            TTEMP = MAX( TEMP, 282e0_fp )
            FACT  = 10.e0_fp**( -2e+0_fp - 4e-2_fp       &
                  *( TTEMP - 294.e+0_fp ) ) / 1e-2_fp

            ! Apply temperature dependence
            GAMMA = GAMMA * FACT

         !----------------
         ! Black Carbon
         !----------------
         CASE ( 9 )  

             ! From IUPAC
             GAMMA = 0.005e+0_fp

         !----------------
         ! Organic Carbon
         !----------------           
         CASE ( 10 )          

            !===========================================================
            ! Based on Thornton, Braban and Abbatt, 2003
            ! N2O5 hydrolysis on sub-micron organic aerosol: the effect
            ! of relative humidity, particle phase and particle size
            !===========================================================
            IF ( RH_P >= 57e+0_fp ) THEN
               GAMMA = 0.03e+0_fp
            ELSE
               GAMMA = RH_P * 5.2e-4_fp
            ENDIF

         !----------------
         ! Sea salt
         ! accum & coarse
         !----------------
         CASE ( 11, 12 )        
            ! This is not used when considering Cl-, xnw 
            ! Based on IUPAC recomendation
            !IF ( RH_P >= 62 ) THEN 
            !   GAMMA = 0.03e+0_fp
            !ELSE
            !   GAMMA = 0.005e+0_fp
            !ENDIF

            IF ( RH_P >= 50 ) THEN 
               GAMMA = 0.02e+0_fp ! Ammann et al., 2013
            ELSE
               GAMMA = 0.003e+0_fp ! Pratte and Rossi, 2006
            ENDIF

         !----------------
         ! Strat. aerosols
         !----------------
         CASE ( 13, 14 )
       
            ! These are handled outside this routine - something
            ! is wrong if AEROTYPE=13 or 14 reaches this point
            WRITE (6,*) 'Stratospheric aerosols should not '
            WRITE (6,*) 'be passed to general N2O5 het. '
            WRITE (6,*) 'chem. subroutine'
            WRITE (6,*) 'AEROSOL TYPE =',AEROTYPE
            CALL GEOS_CHEM_STOP

         !----------------         
         ! Default
         !----------------
         CASE DEFAULT
            WRITE (6,*) 'Not a suitable aerosol surface '
            WRITE (6,*) 'for N2O5 hydrolysis'
            WRITE (6,*) 'AEROSOL TYPE =',AEROTYPE
            CALL GEOS_CHEM_STOP

      END SELECT   
         
    END FUNCTION N2O5
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: Gamma_N2O5_Cl
!
! !DESCRIPTION: Subrountine Gamma_N2O5_Cl computes the GAMMA sticking factor for N2O5 hydrolysis/reaction on Cl- containing aerosols. 
!\\
!\\
! !INTERFACE:
!
    SUBROUTINE GAMMA_N2O5_Cl(C_X, RH, X, Gam_N2O5, r_gp)
!
! !USES:
      Use PhysConstants, ONLY : AVO
!
! !INPUT PARAMETERS: 
!
      REAL(fp),  INTENT(IN) :: C_X       ! Cl- concentration [mol/L]
      INTEGER,   INTENT(IN) :: X         ! X = 1 fine; 2 coarse
      REAL(fp),  INTENT(IN) :: RH        ! Relative humidity [1]
!
! !OUTPUT PARAMETER:
      REAL(fp), INTENT(OUT) :: GAM_N2O5, r_gp
!
!
! !REVISION HISTORY:
!  12 Mar 2018 - X. Wang - Initial version
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      ! Local variables
      REAL(fp) :: te1, te2, te3, Ak2f
      REAL(fp) :: LNIT, LCl, Vol, WaterC
      REAL(fp) :: TTEMP, FACT, RH_P 

      ! Initialize
      GAM_N2O5 = 0.00e+0_fp
      r_gp = 1.0e0_fp
     
      WaterC = AWATER(X) / 18e+6_fp !mol/m3 air
      WaterC = WaterC / 1.0e+6_fp !mol/cm3 air
      LCl  = C_X !mol/L water

      IF (X == 1) THEN
         LNIT = nitConc_SALA
         Vol = AClAREA * AClRADI * 1.0e-3_fp / 3.0e0_fp !L/cm3 air 
      ELSE
         LNIT = nitConc_SALC
         Vol = XAREA(12) * XRADI(12) * 1.0e-3_fp / 3.0e0_fp !L/cm3 air
      ENDIF

      !WaterC = MAX(WaterC / Vol, 1e-20) !mol/L

      ! ClNO2 yield for N2O5+Cl-, Roberts et al. (2009)
      IF (LCl > 1.0e-20) THEN
        r_gp = 1.0e0_fp / ( 55.56e0_fp / (LCl * 450.0e0_fp) + 1.0e0_fp )
      ELSE
        r_gp = 0e0_fp
      ENDIF

      ! Below following Bertram and Thornton (2009)

      IF (LNIT > 1.0e-20) THEN
          te1 = 6.0e-2_fp * (55.56e0_fp / LNIT)
          IF (LCl > 1.0e-20) THEN
             te2 = 29.0e0_fp * (LCl / LNIT)
          ELSE
             te2 = 0.0e+0_fp
          ENDIF
          te3 = 1.0e0_fp - 1.0e0_fp / (te1 + 1.0e0_fp + te2)
      ELSE 
          te3 = 1.0e0_fp
      ENDIF

      ! RH dependence from Kane et al.(2001)
      RH_P  = MIN( RH, 50e+0_fp )

      Ak2f = 2.79e-4_fp + RH_P*(  1.30e-4_fp +    &
                       RH_P*( -3.43e-6_fp +       &
                       RH_P*(  7.52e-8_fp ) ) )

      ! Temperature dependence factor (Cox et al, Cambridge UK)
      TTEMP = MAX( TEMPK, 282e0_fp )
      FACT  = 10.e0_fp**( -2e+0_fp - 4e-2_fp       &
                  *( TTEMP - 294.e+0_fp ) ) / 1e-2_fp

      Ak2f = Ak2f * FACT

      !Ak2f = 3.2e-8*(1.15e6_fp-1.15e6_fp*exp(-0.13e0_fp*WaterC))
      !IF (RH > 50) THEN
      !   Ak2f = 3.0e-2_fp
      !ELSE
      !   Ak2f = 3.0e-3_fp
      !ENDIF

      GAM_N2O5 = Ak2f * te3

      !sensitivity test for N2O5-ClNO2-O3
      !r_gp = 0.0

END SUBROUTINE GAMMA_N2O5_Cl
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HO2
!
! !DESCRIPTION: Function HO2 computes the GAMMA reaction probability
!  for HO2 loss in aerosols based on the recommendation of 
!  Thornton, Jaegle, and McNeill, "Assessing Known Pathways For HO2 Loss in 
!  Aqueous Atmospheric Aerosols: Regional and Global Impacts on Tropospheric 
!  Oxidants" J. Geophys. Res.,  doi:10.1029/2007JD009236, 2008  
!\\
!\\
! !INTERFACE:
!
      FUNCTION HO2( RADIUS,          TEMP,     DENAIR,       &
                    SQM,             HO2DENS,  AEROTYPE,     &
                    CONTINENTAL_PBL, Input_Opt            )  &
                    RESULT( GAMMA )
!
! !USES:
!
      USE Input_Opt_Mod, ONLY : OptInput
      Use PhysConstants, ONLY : AVO, RGASLATM
!
! !INPUT PARAMETERS: 
!
      ! Arguments
      REAL(fp),       INTENT(IN) :: RADIUS          ! Aerosol radius [cm]
      REAL(fp),       INTENT(IN) :: TEMP            ! Temperature [K]
      REAL(fp),       INTENT(IN) :: DENAIR          ! Air density [molec/cm3]
      REAL(fp),       INTENT(IN) :: HO2DENS         ! HO2 density [molec/cm3]
      REAL(fp),       INTENT(IN) :: SQM             ! Square root of MW [g/mol]
      INTEGER,        INTENT(IN) :: AEROTYPE        ! Aerosol type (cf FAST-JX)
      INTEGER,        INTENT(IN) :: CONTINENTAL_PBL ! Flag set to 1 if the box
                                                    !  box is located in the 
                                                    !  continenal boundary 
                                                    !  layer, otherwise 0.
                                                    !  Also check for ICE/SNOW
                                                    !  (to disable this at 
                                                    !  high latitudes).
      TYPE(OptInput), INTENT(IN) :: Input_Opt       ! Input Options object
!
! !RETURN VALUE:
!
      REAL(fp)                   :: GAMMA           ! Reaction probability
      
! !REMARKS:
!  Taken from the old SMVGEAR routine calcrate.F.
!  Gamma(HO2) is a function of aerosol type, radius, temperature.

!  References:
!  ---------------------------------------------------------------
!  (1) Jacob, D.J., Heterogeneous chemistry and tropospheric ozone,
!       Atmos. Environ., 34, 2131-2159, 2000. [full text (pdf)]
!  (2) J. Mao, Fan, S., Jacob, D. J., and Travis, K. R.: Radical
!       loss in the atmosphere from Cu-Fe redox coupling in aerosols,
!       Atmos. Chem. Phys., 13, 509-519, doi:10.5194/acp-13-509-2013,
!       2013.
!
! !REVISION HISTORY:
!  17 May 2013 - M. Payer    - Add improved HO2 uptake (J. Mao)
!  22 May 2013 - M. Payer    - Added option to read GAMMA_HO2 from
!                              input.geos. Recommended value is 0.2
!                              based on Jacob et al (2000) and Mao
!                              et al. (2013).
!  20 Aug 2013 - R. Yantosca - Removed "define.h", this is now obsolete
!  29 Mar 2016 - R. Yantosca - Added ProTeX headers
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      REAL(fp)             :: ALPHA
      REAL(fp)             :: delG, Keq, w, H_eff
      REAL(fp)             :: A1, B1, k1, k2, A, B, C
      REAL(fp)             :: kaq, kmt, o2_ss, fluxrxn, DFKG
      REAL(fp)             :: TEST
!
! !DEFINED PARAMETERS:
!
      ! Ideal gas constant [atm cm3/mol/K]
      REAL(fp),  PARAMETER :: Raq = RGASLATM * 1e+3_fp

      !=================================================================
      ! HO2 begins here!
      !=================================================================

      ! Default value
      GAMMA = 0.0e+0_fp

      ! Error check
      IF (RADIUS.le.1e-30_fp) THEN
         RETURN
      ENDIF

      ! Special handling for various aerosols
      SELECT CASE ( AEROTYPE )

         !----------------
         ! Dust 
         !----------------
         CASE ( 1, 2, 3, 4, 5, 6, 7 )      
                                
            ! Assume default gamma=0.1 on dust aerosols
            ! This is tentative as no lab measurements presently exist
            ! for gamma(HO2) on dust aerosols. We assume the rate to
            ! be fast on dust aerosols as transition metal ion induced
            ! chemistry is likely to occur in a thin aqueous surface layer.
            GAMMA = 0.1e+0_fp

         !----------------
         ! For Sulfate(8), Black Carbon (9), Organic Carbon (10),
         ! Sea-salt accum & coarse (11,12) calculate the 
         ! reaction probability due to self reaction 
         ! by using the algebraic expression in Thornton et al.  (2008)
         ! (equation 7) which is a function of temperature, aerosol radius,
         ! air density and HO2 concentration. 
         !
         ! Transition metal ions (such as copper and iron) in sea-salt and 
         ! carbonaceous aerosols are complexed to ligands and/or exist at 
         ! a concentration too low to catalyze HO2 loss efficiently, so we 
         ! apply the HO2 self reaction expression directly for these aerosols.
         ! 
         ! In the case of sulfate aerosol, the aerosols likely
         ! contain copper in the continental boundary layer and
         ! HO2 uptake proceeds rapidly. To account for the metal catalyzed
         ! uptake, we assume gamma(HO2)=0.07 (in the mid-range of the recommended
         ! 0.04-0.1 by Thornton et al, based on observed copper concentrations
         ! in the US boundary layer). Outside the continental boundary layer, we
         ! use the HO2-only algebraic expression.
         !
         ! SDE 04/18/13: Added stratospheric sulfur aerosols
         !
         !----------------
         CASE ( 8, 9, 10, 11, 12, 13 )  

            ! Mean molecular speed [cm/s]
            w = 14550.5e+0_fp * sqrt(TEMP/(SQM*SQM))

            ! DFKG = Gas phase diffusion coeff [cm2/s]
            DFKG  = 9.45E+17_fp/DENAIR * SQRT(TEMP) *      &
                    SQRT(3.472E-2_fp + 1.E+0_fp/(SQM*SQM))

            !calculate T-dependent solubility and aq. reaction rate constants
            ! hydronium ion concentration
            ! A1 = 1.+(Keq/hplus) 
            ! with Keq = 2.1d-5 [M], Equilibrium constant for 
            ! HO2aq = H+ + O2- (Jacob, 2000)
            !      hplus=10.e+0_fp^(-pH), with pH = 5
            ! B1 = Req * TEMP
            ! with Req = 1.987d-3 [kcal/K/mol], Ideal gas constant
            ! Note that we assume a constant pH of 5.
            A1 = 1.+ (2.1e-5_fp / (10.e+0_fp**(-5) ) )
            B1 = 1.987e-3_fp * TEMP

            ! Free energy change for solvation of HO2 (Hanson 1992, Golden 1991)
            ! in [kcal/mol]:
            ! delG = -4.9-(TEMP-298e+0_fp)*delS
            ! with delS=-0.023  [kcal/mol/K],  Entropy change for solvation of HO2
            delG  = -4.9e+0_fp - (TEMP-298.e+0_fp) * (-0.023)
            H_eff = exp( -delG / B1 ) * A1

            ! Estimated temp dependent value for HO2 + O2- (k1) and 
            ! HO2+HO2 (see Jacob 1989)
            k1  =   1.58e+10_fp * exp( -3. / B1 )
            k2  =   2.4e+9_fp   * exp( -4.7 / B1 )
            kaq = ( k1 * (A1 - 1.e+0_fp) + k2) / (A1**2)

            ! Calculate the mass transfer rate constant and s.s. conc. of 
            ! total HO2 in the aqueous phase:
            ! kmt = (RADIUS/DFKG + 4e+0_fp/w/alpha)^(-1)
            ! with alpha = mass accomodation coefficient, assumed 
            ! to be 1 (Thornton et al.)
            kmt = 1.e+0_fp/( RADIUS/DFKG + 4e+0_fp/w/1. )

            !use quadratic formula to obtain [O2-] in particle of radius RADIUS
            A = -2e+0_fp * kaq
            B = -3e+0_fp * kmt / RADIUS / (H_eff * 0.082 * TEMP)
            C =  3e+0_fp * kmt * HO2DENS * 1000e+0_fp / RADIUS / AVO

            ! Error check that B^2-(4e+0_fp*A*C) is not negative
            TEST= B**2-(4e+0_fp*A*C)
            IF ( TEST < 0e+0_fp ) THEN
                GAMMA = 0e+0_fp
            ELSE
                ! Calculate the concentration of O2- in the aerosol
                o2_ss= ( -B  -sqrt(B**2-(4e+0_fp*A*C)) )/(2e+0_fp*A)

                ! Calculate the reactive flux
                fluxrxn = kmt*HO2DENS - o2_ss*AVO*kmt/H_eff/Raq/TEMP

                IF ( fluxrxn <= 0e0_fp ) THEN
                   GAMMA = 0e+0_fp
                ELSE
                   ! Gamma for HO2 at TEMP, ho2, and RADIUS given
                   GAMMA = 1./( ( ( HO2DENS/fluxrxn ) -              &
                                  ( RADIUS/DFKG ) ) * w / 4.e+0_fp )
                ENDIF
            ENDIF
            ! For sulfate aerosols, check whether we are in
            ! the continental boundary layer, in which case
            ! copper catalyzed HO2 uptake likely dominates and
            ! speeds up the reaction: we assume gamma=0.07,
            ! which is in the middle of the 0.04-0.1 range recommended
            ! by Thornton et al. (2008)
            !
            IF ( AEROTYPE == 8 .and. CONTINENTAL_PBL == 1) THEN
                GAMMA = 0.07
            ENDIF 

         !----------------
         ! NAT/ice (SDE 04/18/13)
         !----------------
         CASE ( 14 )
       
            GAMMA = 0.e+0_fp

         !----------------
         ! Default
         !----------------
         CASE DEFAULT
            WRITE (6,*) 'Not a suitable aerosol surface '
            WRITE (6,*) 'for HO2 uptake'
            WRITE (6,*) 'AEROSOL TYPE =',AEROTYPE
            CALL GEOS_CHEM_STOP

      END SELECT
     
      ! If negative value is calculated, set it to zero
      IF ( GAMMA  <= 0e+0_fp ) GAMMA = 0e+0_fp

      ! This is for the improved HO2 uptake (J. Mao)
      GAMMA = Input_Opt%GAMMA_HO2

    END FUNCTION HO2
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: EPOXUPTK
!
! !DESCRIPTION: Function EPOXUPTK computes the GAMMA sticking factor for
! EPOXUPTK hydrolysis to form 2-methyltetrols (AITET). (eam, 2014).
!\\
!\\
! !INTERFACE:
!
    FUNCTION EPOXUPTK( AERAREA, AERRAD,  TEMP,  SQMW,              &
                       HENRY,   KHPLUS,  HPLUS, KNUC,  SULF, NITR, &
                       KGACID,  BISULF,  KHYDRO ) &
             RESULT( GAMMA )
!
! !USES:
!
      USE Input_Opt_Mod, ONLY : OptInput
      USE PhysConstants, ONLY : RGASLATM
      USE ERROR_MOD,     ONLY : IT_IS_NAN
!
! !INPUT PARAMETERS: 
!
      REAL(fp), INTENT(IN) :: AERRAD   ! Aerosol radius [cm]
      REAL(fp), INTENT(IN) :: AERAREA  ! Aerosol surf. area [cm2/cm3]
      REAL(fp), INTENT(IN) :: TEMP     ! Temperature [K]
      REAL(fp), INTENT(IN) :: SQMW     ! Square root of the molecular weight
      REAL(fp), INTENT(IN) :: HENRY    ! Henry's Law constant [M/atm]
      REAL(fp), INTENT(IN) :: KHPLUS   ! 1st order rxn rate (acid-catalyzed ring
                                       ! opening)
      REAL(fp), INTENT(IN) :: HPLUS    ! Proton activity [unitless] and [H+] [M]
      REAL(fp), INTENT(IN) :: KNUC     ! 1st order rxn rate due to specific 
                                       ! nucleophiles (SO4, NO3)
      REAL(fp), INTENT(IN) :: SULF     ! Sulfate concentration [M]
      REAL(fp), INTENT(IN) :: NITR     ! Nitrate concentration [M]
      REAL(fp), INTENT(IN) :: KGACID   ! 1st order rxn rate due to general acids
                                       ! (bisulfate in this case)
      REAL(fp), INTENT(IN) :: BISULF   ! Bisulfate concentration [M]
      REAL(fp), INTENT(IN) :: KHYDRO   ! Hydrolysis rate of alkylnitrates [1/s]
!
! !RETURN VALUE:
!
      REAL(fp)             :: GAMMA    ! Reaction probability
      
! !REMARKS:
! Calculation is only done for inorganic aqueous phase aerosols
!                                                                             .
! This calculation uses the parameterization of Gaston et al., EST, 2014.
!                                                                             .
! Redistribution of products (e.g. AITET) to yield organosulfates and
! organonitrates is done in SOA_CHEMISTRY in carbon_mod.F.
! This is only done for IEPOX and IMAE if it's an SOA simulation
!
! !REVISION HISTORY:
!  15 Jun 2017 - M. Sulprizio- Initial version based on calcrate.F from E.Marais
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      ! Local variables
      REAL(fp)             :: AERVOL   ! Aerosol volume [cm3/cm3]
      REAL(fp)             :: KPART    ! Particle-phase reaction rate [1/s]
      REAL(fp)             :: XMMS     ! Mean molecular speed [cm/s]
      REAL(fp)             :: VAL1, VAL2, VAL3  ! Terms for calculating GAMMA
      REAL(fp)             :: VALTMP
!
! !DEFINED PARAMETERS:
!
      ! Gas-phase diffusion constant [cm2/s]:
      REAL(fp), PARAMETER  :: DIFF_N2O5_STD = 1.0e-1_fp

      ! Mass accommodation coefficient [unitless]:
      REAL(fp), PARAMETER  :: MACOEFF = 1.0e-1_fp

      !=================================================================
      ! EPOXUPTK begins here!
      !=================================================================

      ! Initialize
      GAMMA  = 0.0_fp
      AERVOL = 0.0_fp
      KPART  = 0.0_fp
      XMMS   = 0.0_fp
      VAL1   = 0.0_fp
      VAL2   = 0.0_fp
      VAL3   = 0.0_fp
      VALTMP = 0.0_fp
      
      ! Calculate aerosol volume (use formula in aerosol_mod.F):
      AERVOL = (AERAREA * AERRAD)/3.0e+0_fp

      ! Calculate mean molecular speed [cm/s]:
      XMMS = SQRT( (2.117e+8_fp * TEMP) / (SQMW * SQMW) )

      ! Calculate first-order particle-phase reaction rate:
      ! (assume [H+] = proton activity)
      ! KHYDRO is only important for alkylnitrates (not currently used).
      KPART = ( KHPLUS*HPLUS )               + &
              ( KNUC*HPLUS*( NITR + SULF ) ) + &
              ( KGACID*BISULF )              + &
              ( KHYDRO )
      
      ! Calculate the first uptake parameterization term:
      VAL1 = ( AERRAD * XMMS )/( 4.e+0_fp * DIFF_N2O5_STD )
      
      ! Calculate the second uptake parameterization term:
      VAL2 = ( 1.e+0_fp/MACOEFF )

      ! Calculate the third uptake parameterization term:
      IF ( AERAREA > 0.0_fp .and. XMMS > 0.0_fp ) THEN
         VALTMP = ( 4.e+0_fp * AERVOL * RGASLATM * TEMP * HENRY * KPART ) / &
                  ( AERAREA * XMMS )
      ENDIF
      IF ( VALTMP .GT. 0 ) THEN
         VAL3 = 1.e+0_fp / VALTMP
      ELSE
         VAL3 = 0.0e+0_fp
      ENDIF

      ! Account for small reaction rates:
      IF ( KPART .LT. 1.e-8_fp ) THEN

         GAMMA = TINY(1e+0_fp)

      ELSE
         
         ! Calculate the uptake coefficient:
         GAMMA = 1.e+0_fp/( VAL1 + VAL2 + VAL3 )

      ENDIF

      ! Fail safes for negative, very very small, and NAN GAMMA values:
      IF ( GAMMA  .lt. 0.0e+0_fp )    GAMMA = TINY(1e+0_fp)
      IF ( IT_IS_NAN( GAMMA ) )       GAMMA = TINY(1e+0_fp)
      IF ( GAMMA .lt. TINY(1e+0_fp) ) GAMMA = TINY(1e+0_fp)

      END FUNCTION EPOXUPTK
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: Cld_Params
!
! !DESCRIPTION: Subroutine CLD_PARAMS returns ice and liquid cloud 
!  parameters based on State_Met.off of cloud particles.
!\\
!\\
! !INTERFACE:
!
    SUBROUTINE CLD_PARAMS( I,      J,      L,    DENAIR,            &
                           VAir,   T,      QL,   QI,     State_Met, &
                           rLiq,   ALiq,   VLiq, &
                           rIce,   AIce,   VIce )

!
! !USES:
!
      USE State_Met_Mod, ONLY : MetState
      USE PhysConstants, ONLY : RSTARG, PI
!
! !INPUT PARAMETERS:
!
      INTEGER,        INTENT(IN)  :: I         ! Longitude index
      INTEGER,        INTENT(IN)  :: J         ! Latitude  index
      INTEGER,        INTENT(IN)  :: L         ! Altitude  index
      REAL(fp),       INTENT(IN)  :: DENAIR    ! Density of air [#/cm3]
      REAL(fp),       INTENT(IN)  :: VAir      ! Volume of air [cm3]
      REAL(fp),       INTENT(IN)  :: T         ! Temperature [K]
      REAL(fp),       INTENT(IN)  :: QL, QI    ! Cloud water mixing ratio [kg/kg]
      TYPE(MetState), INTENT(IN)  :: State_Met ! Meteorology State object
!
! !OUTPUT PARAMETERS:
!
      REAL(fp),       INTENT(OUT) :: rLiq     ! Radius of liquid cloud droplets (cm)
      REAL(fp),       INTENT(OUT) :: rIce     ! Radius of ice cloud crystals (cm)
      REAL(fp),       INTENT(OUT) :: ALiq     ! Sfc area of liq. cloud (cm2/cm3)
      REAL(fp),       INTENT(OUT) :: AIce     ! Sfc area of ice cloud (cm2/cm3)
      REAL(fp),       INTENT(OUT) :: VLiq     ! Volume of liq. cloud (cm3/cm3)
      REAL(fp),       INTENT(OUT) :: VIce     ! Volume of ice cloud (cm3/cm3)
!
! !REMARKS:
!
! !REVISION HISTORY:
!  21 Dec 2016 - S. D. Eastham - Adapted from CLD1K_BrNO3
!  24 Aug 2017 - M. Sulprizio- Remove support for GCAP, GEOS-4, GEOS-5 and MERRA
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !DEFINED PARAMETERS:
!
      ! Cloud droplet radius in continental warm clouds [cm]
      REAL(fp), PARAMETER :: XCLDR_CONT =  6.e-4_fp

      ! Cloud droplet radius in marine warm clouds [cm]
      REAL(fp), PARAMETER :: XCLDR_MARI = 10.e-4_fp

      ! Ice cloud droplet radius [cm]
      !REAL(fp), PARAMETER :: XCLDrIce = 75.e-4_fp
      ! Change to ice droplet radius based on observations.
      ! lei, 02/20/18
      REAL(fp), PARAMETER :: XCLDrIce = 38.53e-4_fp

      ! Sticking coefficient
      REAL(fp), PARAMETER :: alpha = 0.3_fp

      ! Density of H2O [kg/cm3]
      REAL(fp), PARAMETER :: dens_h2o = 0.001e+0_fp
!
! !LOCAL VARIABLES:
!
      REAL(fp)            :: nu         ! Mean molecular speed
      REAL(fp)            :: RADIUS     ! Radius of cloud droplet      [cm]
      REAL(fp)            :: SQM        ! Square root of molec. weight [g/mol]
      REAL(fp)            :: STK        ! Square root of temperature   [K]
      REAL(fp)            :: DFKG       ! Gas diffusion coefficient    [cm2/s]
      REAL(fp)            :: AREA_L     ! Surface area (liquid)        [cm2/cm3]
      REAL(fp)            :: AREA_I     ! Surface area (ice) )         [cm2/cm3]
      REAL(fp)            :: Vcl, Vci   ! Volume of the cloud (liq and ice) [cm3]
      Real(fp)            :: MX         ! Molar mass                   [kg/mol]
      LOGICAL             :: IS_LAND, IS_ICE, Is_Warm
   
      ! Pointers
      REAL(fp), POINTER   :: AD(:,:,:)
      REAL(fp), POINTER   :: CLDF(:,:,:)
      REAL(fp), POINTER   :: FRLAND(:,:)
      REAL(fp), POINTER   :: FROCEAN(:,:)

      !=================================================================
      ! CLD_PARAMS begins here!
      !=================================================================

      ! Initialize pointers
      AD      => State_Met%AD
      CLDF    => State_Met%CLDF
      FRLAND  => State_Met%FRLAND
      FROCEAN => State_Met%FROCEAN

      ! Fixed for now
      rIce = xCldrIce
 
      ! Quick test - is there any cloud?
      IF (((QL.le.0.0e+0_fp).and.(QL.le.0.0e+0_fp)).or.(CLDF(I,J,L).le.0.0e+0_fp)) THEN
         rLiq = xCldR_Cont
         ALiq = 0.0e+0_fp
         VLiq = 0.0e+0_fp
         AIce = 0.0e+0_fp
         VIce = 0.0e+0_fp
         Return
      ENDIF

      ! Is this land?
      ! LWI=1 and ALBEDO less than 69.5% is a LAND box 
      IS_LAND = ( NINT( State_Met%LWI(I,J) ) == 1       .and. &
                     State_Met%ALBD(I,J)  <  0.695e+0_fp )

      ! Is this ice?
      ! LWI=2 or ALBEDO > 69.5% is ice
      IS_ICE = ( NINT( State_Met%LWI(I,J) ) == 2       .or. &
                    State_Met%ALBD(I,J)  >= 0.695e+0_fp )

      ! ----------------------------------------------
      ! Test conditions to see if we want to continue
      ! with respect to liquid clouds.
      ! ----------------------------------------------

      ! continental or marine clouds only...
      IF ( (FRLAND (I,J) > 0) .or. (FROCEAN(I,J) > 0) ) THEN
      ! Above line is to skip over land ice (Greenland and Antartica). This
      ! should do the same (and also work for GEOS-5, but leave above for now).
      !IF ( IS_LAND .and. .not. IS_ICE  ) THEN
         ! do we have clouds? and do we have warm temperatures?
         Is_Warm = ((CLDF(I,J,L) > 0) .and. (T > 258.0))
      ELSE
         Is_Warm = .FALSE.
      ENDIF

      ! ----------------------------------------------
      !   calculate the surface area of cloud droplets
      !   in the given grid box, assuming 1 of 2
      !   conditions:
      !     a. marine warm cloud
      !       or
      !     b. continental warm cloud
      !
      !
      !   * Calculation for area is derived follows,
      !     assuming that RADIUS is constant:
      !
      !                         4/3 (pi) (RADIUS)**3
      !  1) FC = Vc / Vb = N  -------------------------
      !                                  Vb
      !
      !
      !       where N      = number of cloud droplets
      !             RADIUS = radius of cloud droplet
      !             Vc     = volumn of the cloud
      !             Vb     = volumn of the box = AIRVOL (in GEOS-Chem)
      !
      !
      !                     Vb
      !  2) N = FC --------------------
      !            4/3 (pi) (RADIUS)**3
      !
      !
      !  So the surface area [m2] is calculated as
      !
      !  3) total surface A = N * 4 * (pi) * (RADIUS)**2
      !
      !                  3*Vb
      !          = FC ----------
      !                 RADIUS
      !
      !  4) for this routine though we want
      !     AREA in [cm2/cm3], surface area to volume air:
      !
      !                   3
      !     AREA = FC ---------
      !                RADIUS (in cm)
      !
      !
      !    or    
      !                   3 x Vc
      !     AREA =  -----------------
      !              AIRVOL x RADIUS      (in cm)
      ! ----------------------------------------------
      IF ( FRLAND(I,J) > FROCEAN(I,J) ) THEN
         ! Continental cloud droplet radius [cm]
         rLiq = XCLDR_CONT
      ELSE
         ! Marine cloud droplet radius [cm]
         rLiq = XCLDR_MARI
      ENDIF

      ! get the volume of cloud [cm3]
      ! QL is [g/g]
      VLiq = QL * AD(I,J,L) / dens_h2o
      VIce = QI * AD(I,J,L) / dens_h2o
  
      ! Only want warm (continental or marine) liquid clouds
      IF ( .not. Is_Warm ) THEN
         VLiq = 0.e+0_fp
      ENDIF

      ! now calculate the cloud droplet surface area density
      ! ALiq and AIce are in cm2/cm3
      ALiq = 3.e+0_fp * (VLiq/VAir) / rLiq ! keep Radius in [cm]
      ! Increase Ice surface area by 10 to account for the
      ! irragular surface, lei, 11/19/18
      !AIce = 3.e+0_fp * (VIce/VAir) / rIce ! keep Radius in [cm]
      AIce = 3.e+1_fp * (VIce/VAir) / rIce ! keep Radius in [cm]

      ! Free Pointers
      NULLIFY( AD      )
      NULLIFY( CLDF    )
      NULLIFY( FRLAND  )
      NULLIFY( FROCEAN )

    END SUBROUTINE Cld_Params
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: Get_Halide_CldConc
!
! !DESCRIPTION: Subroutine GET_HALIDE_CLDCONC returns the in-cloud concentration
!  of halide
!\\
!\\
! !INTERFACE:
!
      SUBROUTINE GET_HALIDE_CLDCONC( n_x, VLiq, VIce, VAir, TK, CF, conc_x)
!
! !USES:
!
!
! !INPUT PARAMETERS:
!
      REAL(fp),  INTENT(IN) :: n_x  ! Number density [#/cm3] (gas + aerosol)
      REAL(fp),  INTENT(IN) :: VAir    ! Volume of air [cm3]
      REAL(fp),  INTENT(IN) :: VLiq, VIce ! Volume of the cloud (liq and ice) [cm3]
      REAL(fp),  INTENT(IN) :: TK      ! Air temperature [K]
      REAL(fp),  INTENT(IN) :: CF      ! Cloud fraction

!
! !RETURN VALUE:
!
      REAL(fp), INTENT(OUT) :: conc_x ! Liq. phase molar concentration [mol/kg-water]
!
! !REMARKS:
!
! !REVISION HISTORY:
!  01 Feb 2018 - X. Wang       - Initial version
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      REAL(fp)            :: V_tot, dr_ratio, t2l ! 
   
      !=================================================================
      ! GET_HALIDE_CLDCONC begins here!
      !=================================================================

      !---------------------------------------------------------------
      ! jas, 07/30/2014 (SETUP d/r ratio for ice cloud droplets)
      ! V_liq = 4pi/3 ( r^3 - (r - r*(d/r))^3 = (r^3 - r^3*(1 - d/r)^3) = r^3 (1 - (1 - d/r)^3
      ! V_tot / V_liq = 1 / (1 - (1 - d/r)^3))
      DR_RATIO = 2e-2_fp
      T2L = 1.0e0_fp / ( 1.0e0_fp - (1.0e0_fp - DR_RATIO)**3.0e0_fp )
      !---------------------------------------------------------------

      !V_tot = (VLiq/VAir) + ((VIce/VAir) / T2L) + &
      !         SA_SALT * R_SALT / 3.0e0_fp  ! (cm3(liq)/cm3(air)

      !For volume, only consider cloud, cm3(liq)/cm3(air), xnw 02/05/18
      V_tot = (VLiq/VAir) + ((VIce/VAir) / T2L) 

      !For X-, also only consider those in cloud, xnw 02/05/18
      conc_x = conc_x * CF

      IF (V_tot.lt.1.0e-20) THEN
         conc_x = 1.0e-20_fp
         Return
      ENDIF
      
      !IF only considering X- from thermodynamics
      conc_x = n_x / (V_tot * AVO * 1.0e-3_fp) ! Halide in (mol/L)

      conc_x = min(conc_x,5.0e0_fp)
      conc_x = max(conc_x,1.0e-20_fp)

      END SUBROUTINE GET_HALIDE_CLDCONC
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: Get_Halide_CldConc_g
!
! !DESCRIPTION: Subroutine GET_HALIDE_CLDCONC_G returns the in-cloud concentration
!  of bromide and chloride (Br- and Cl-) contributed from the dissolved gases.
!\\
!\\
! !INTERFACE:
!
      SUBROUTINE GET_HALIDE_CLDCONC_g( HBr, HCl, VLiq, VIce, VAir, TK, CF, br_conc, cl_conc )

!
! !USES:
!
! !INPUT PARAMETERS:
!
      REAL(fp),  INTENT(IN) :: HCl, HBr  ! Number density [#/cm3]
      REAL(fp),  INTENT(IN) :: VAir    ! Volume of air [cm3]
      REAL(fp),  INTENT(IN) :: VLiq, VIce ! Volume of the cloud (liq and ice) [cm3]
      REAL(fp),  INTENT(IN) :: TK      ! Air temperature [K]
      REAL(fp),  INTENT(IN) :: CF      ! Cloud fraction
!
! !RETURN VALUE:
!
      REAL(fp), INTENT(OUT) :: cl_conc, br_conc ! Liq. phase molar concentration [mol/kg-water]
!
! !REMARKS:
!
! !REVISION HISTORY:
!  01 Apr 2018 - X. Wang       - Initial version
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      REAL(fp)            :: n_br, n_cl ! dissolved bromide and chloride [#/cm3(air)]
      REAL(fp)            :: V_tot, dr_ratio, t2l ! 
      REAL(fp)            :: L2G, F_L

      !=================================================================
      ! GET_HALIDE_CLDCONC_G begins here!
      !=================================================================

      !--------------------------------------------------------------- 
      ! jas, 07/30/2014 (SETUP d/r ratio for ice cloud droplets)
      ! V_liq = 4pi/3 ( r^3 - (r - r*(d/r))^3 = (r^3 - r^3*(1 - d/r)^3) = r^3 (1
      ! - (1 - d/r)^3
      ! V_tot / V_liq = 1 / (1 - (1 - d/r)^3))
      DR_RATIO = 2e-2_fp
      T2L = 1.0e0_fp / ( 1.0e0_fp - (1.0e0_fp - DR_RATIO)**3.0e0_fp )
      !--------------------------------------------------------------- 

      V_tot = (VLiq/VAir) + ((VIce/VAir) / T2L) ! (cm3(liq)/cm3(air)
      V_tot = V_tot / CF ! only consider in cloud

      IF (V_tot.lt.1.0e-20) THEN
         br_conc = 1.0e-20_fp
         cl_conc = 1.0e-20_fp
         Return
      ENDIF

      ! Chloride (Assuming ph=4.5)
      CALL COMPUTE_L2G_LOCAL( 1.1e11_fp, 9000.0e0_fp, 0.0e+0_fp, TK, V_tot, L2G)
      F_L = L2G/(1.0e0_fp + L2G)
      cl_conc = F_L * HCl / (V_tot * AVO * 1.0e-3_fp) ! [Cl-] in (mol/L)
      cl_conc = min(cl_conc,5.0e0_fp)
      cl_conc = max(cl_conc,1.0e-20_fp)

      ! Bromide (Assuming ph=4.5)
      CALL COMPUTE_L2G_LOCAL( 7.1e13_fp, 10200.0e0_fp, 0.0e+0_fp, TK, V_tot, L2G)
      F_L = L2G/(1.0e0_fp + L2G)
      br_conc = F_L * HBr / (V_tot * AVO * 1.0e-3_fp) ! [Br-] in (mol/L)

      br_conc = min(br_conc,5.0e0_fp)
      br_conc = max(br_conc,1.0e-20_fp)

      END SUBROUTINE GET_HALIDE_CLDCONC_G
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: Get_Halide_SSAConc_g
!
! !DESCRIPTION: Function GET\_HALIDE\_SSACONC_g calculates concentration of a
!               halide in sea salt aerosol contributed from gas (for HBr here)
!\\
!\\
! !INTERFACE:
!
      SUBROUTINE GET_HALIDE_SSACONC_g( n_x, surf_area, r_w, TK, conc_x )
!
! !DESCRIPTION: Function GET\_HALIDE\_SSACONC calculates concentration of a
!               halide in sea salt aerosol.
!
! !OUTPUT PARAMETER:
      ! concentration of X- in SALX (mol/L)
      REAL(fp)                         :: conc_x
! !INPUT PARAMETERS:
      ! n_x = X-(ssa) number density (#/cm3), surf_area = AERO surface area
      ! conc (cm2/cm3), r_w = AERO wet radius (cm)
      REAL(fp), INTENT(IN)             :: n_x, surf_area, r_w, TK

!
! !REVISION HISTORY:
!  15 Jul 2018 - X. Wang - Initial version
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
!
      !REAL(fp),  PARAMETER :: con_NA      = 6.0221413e23_fp ! #/mol
      REAL(fp)             :: V_tot, F_L, L2G

      V_tot = surf_area * r_w * 0.3333333e0_fp * 1e-3_fp ! L(liq)/cm3(air)
      IF (V_tot .le. 1.0e-20) THEN
         conc_x = 1.0e-20_fp
         Return
      ELSE
         ! (assume pH = 0)
         CALL COMPUTE_L2G_LOCAL( 2.2e9_fp, 10200.0e0_fp, 0.0e+0_fp, TK, V_tot,L2G)
         F_L = L2G/(1.0e0_fp + L2G)
         conc_x = F_L * n_x / (V_tot * AVO * 1.0e-3_fp) ! [Br-] in (mol/L)
         !conc_x =  (n_x / AVO) / V_tot ! mol/L
         conc_x = MIN(conc_x,5.0e0_fp)
         conc_x = MAX(conc_x,1.0e-20_fp)
      ENDIF

      END SUBROUTINE GET_HALIDE_SSACONC_g
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: Get_Halide_SSAConc
!
! !DESCRIPTION: Function GET\_HALIDE\_SSACONC calculates concentration of a
!               halide in sea salt aerosol.
!\\
!\\
! !INTERFACE:
!
      SUBROUTINE GET_HALIDE_SSACONC( n_x, surf_area, r_w, conc_x )
!
! !DESCRIPTION: Function GET\_HALIDE\_SSACONC calculates concentration of a
!               halide in sea salt aerosol.
!
! !OUTPUT PARAMETER:
      ! concentration of X- in SALX (mol/L)
      REAL(fp)                         :: conc_x
! !INPUT PARAMETERS:
      ! n_x = X-(ssa) number density (#/cm3), surf_area = AERO surface area
      ! conc (cm2/cm3), r_w = AERO wet radius (cm)
      REAL(fp), INTENT(IN)             :: n_x, surf_area, r_w

!
! !REVISION HISTORY:
!  25 Jul 2014 - J. Schmidt - Initial version
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
!
      !REAL(fp),  PARAMETER :: con_NA      = 6.0221413e23_fp ! #/mol
      REAL(fp)             :: V_tot

      V_tot = surf_area * r_w * 0.3333333e0_fp * 1e-3_fp ! L(liq)/cm3(air)
      IF (V_tot .le. 1.0e-20) THEN
         conc_x = 1.0e-20_fp
         Return
      ELSE
         ! This calculation can be used for both SSA X- concentration and for
         ! those out of cloud only. For X- out of cloud only, V_tot =
         ! V_tot*(1-CF), n_x = n_x*(1-CF), so (1-CF) is canceled. 
         ! xnw, 02/05/18
         conc_x =  (n_x / AVO) / V_tot ! mol/L
         conc_x = MIN(conc_x,5.0e0_fp)
         conc_x = MAX(conc_x,1.0e-20_fp)
      ENDIF

      END SUBROUTINE GET_HALIDE_SSACONC
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: Compute_L2G_Local
!
! !DESCRIPTION: Subroutine COMPUTE_L2G_LOCAL is a local copy of the liquid-gas
!  partitioning routine in GEOS-Chem's wetscav_mod.F file.
!\\
!\\
! !INTERFACE:
!
      SUBROUTINE COMPUTE_L2G_LOCAL( K0, CR, pKa, TK, H2OLIQ, L2G )
!
! !USES:
!
      USE Henry_Mod, ONLY : Calc_KH
      USE Henry_Mod, ONLY : Calc_Heff
!     
! !INPUT PARAMETERS: 
!
      REAL(fp), INTENT(IN)  :: K0     ! Henry's solubility constant [M/atm]
      REAL(fp), INTENT(IN)  :: CR     ! Henry's volatility constant [K] 
      REAL(fp), INTENT(IN)  :: pKa    ! Henry's pH correction factor [1]
      REAL(fp), INTENT(IN)  :: TK     ! Temperature [K]
      REAL(fp), INTENT(IN)  :: H2OLIQ ! Liquid water content [cm3 H2O/cm3 air]
!                                     
! !OUTPUT PARAMETERS:                 
!                                     
      REAL(fp), INTENT(OUT) :: L2G    ! Cliq/Cgas ratio [1]
!
! !REMARKS:
!  The ratio Cliq / Cgas is obtained via Henry's law.  The appropriate 
!  values of Kstar298 and H298_R must be supplied for each species.  
!  (cf Jacob et al 2000, p. 3)
! 
! !REVISION HISTORY: 
!  23 Feb 2000 - R. Yantosca - Initial version
!  (1 ) Bundled into "wetscav_mod.f" (bmy, 11/8/02)
!  16 Sep 2010 - R. Yantosca - Added ProTeX headers
!  10-Jan-2011 - H. Amos - Corrected the units on KStar298 from moles/atm
!                          to M/atm
!  15-May-2013 - F. Paulot - Fix R constant
!  08 Dec 2015 - R. Yantosca - Now use functions from henry_mod.F
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      INTEGER  :: RC
      REAL(fp) :: HEFF, KH, pH, TK_8

      !=================================================================
      ! COMPUTE_L2G_LOCAL begins here!
      !=================================================================

      ! Cast temperature to REAL*8
      TK_8 = TK

      ! For wetdep, we assume a pH of 4.5 for rainwater
      pH = 4.5_fp

      ! Calculate the Henry's law constant
      CALL CALC_KH( K0, CR, TK_8, KH, RC )

      ! Calculate effective Henry's law constant, corrected for pH
      ! (for those species that have a defined pKa value)
      CALL CALC_HEFF( pKa, pH, KH, HEFF, RC )

      ! Use Henry's Law to get the ratio:
      ! [ mixing ratio in liquid phase / mixing ratio in gas phase ]
      L2G   = HEFF * H2OLIQ

      END SUBROUTINE COMPUTE_L2G_LOCAL
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: Cld1k_XNO3
!
! !DESCRIPTION: Function CLD1K\_XNO3 calculates the rate constant for
!  heterogeneous cycling of XNO3 off of cloud particles.
!\\
!\\
! !INTERFACE:
!
    FUNCTION CLD1K_XNO3( denAir, TK, rLiq, rIce, ALiq, AIce, &
                         MX_gmol, AlphaX )    RESULT( cld1k )

!
! !USES:
!
!      USE PhysConstants, ONLY : PI
!
! !INPUT PARAMETERS:
!
      REAL(fp),       Intent(IN) :: DENAIR   ! Density of air [#/cm3]
      REAL(fp),       Intent(In) :: TK       ! Air temperature [K]
      REAL(fp),       Intent(In) :: rLiq     ! Radius of liquid cloud drops [cm]
      REAL(fp),       Intent(In) :: rIce     ! Radius of ice cloud crystals [cm]
      REAL(fp),       Intent(In) :: ALiq     ! Surface area (liquid) [cm2/cm3]
      REAL(fp),       Intent(In) :: AIce     ! Surface area (ice) ) [cm2/cm3]
      REAL(fp),       Intent(IN) :: MX_gmol  ! Molecular mass of XNO3 [g/mol]
      REAL(fp),       Intent(IN) :: AlphaX   ! XNO3 accomodation coef [unitless]
!
! !RETURN VALUE:
!
      REAL(fp)                   :: cld1k    ! Rate constant for heterogeneous
                                             ! cycling of BrNO3 off of cloud 
                                             ! particles
!
! !REMARKS:
!
! !REVISION HISTORY:
!  27 Feb 2011 - J. Parrella - Initial version
!  22 May 2012 - M. Payer    - Added ProTeX headers
!  09 Nov 2012 - M. Payer    - Replaced all met field arrays with State_Met
!                              derived type object
!  06 Nov 2014 - R. Yantosca - Now use State_Met%CLDF(I,J,L)
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      REAL(fp)             :: SQM        ! Square root of molec. weight [g/mol]
      REAL(fp)             :: STK        ! Square root of temperature   [K]
      REAL(fp)             :: DFKG       ! Gas diffusion coefficient    [cm2/s]

      !=================================================================
      ! CLD1K_XNO3 begins here!
      !=================================================================

      ! Quick test - is there any cloud?
      IF ((ALiq.le.0.0e+0_fp).and.(AIce.le.0.0e+0_fp)) THEN
         cld1k = 0.0e+0_fp
         Return
      ENDIF

      ! ------------------------------------------------------------
      !   Calculate the 1st order rate constant for XNO3 hydrolysis.
      !
      !   (a) calculate the gas phase diffusion coefficient;
      !
      !   (b) calculate the hydrolysis rxn rate.
      ! ------------------------------------------------------------
      SQM = sqrt(MX_gmol)    ! square root of molar mass [g/mole]
      STK = sqrt(TK) ! square root of temperature [K]

      ! DFKG = Gas phase diffusion coeff [cm2/s] (order of 0.1)
      DFKG  = 9.45E+17_fp/DENAIR * STK * SQRT(3.472E-2_fp + 1.E+0_fp/(SQM*SQM))

      ! Compute ARSL1K according to the formula listed above
      ! Sum contribution from ice and liquid clouds
      cld1k = ALiq / ( rLiq/DFKG + 2.749064E-4 * SQM/(ALPHAX*STK) )
      cld1k = AIce / ( rIce/DFKG + 2.749064E-4 * SQM/(ALPHAX*STK) ) + cld1k

    END FUNCTION CLD1K_XNO3
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: FcrO2HO2
!
! !DESCRIPTION: !fgap, based on saunder 2003 k14
!\\
!\\
! !INTERFACE:
!
    FUNCTION FCRO2HO2( XCARBN ) RESULT( FC_RO2HO2 )
!
! !INPUT PARAMETERS:
!
      REAL(fp), INTENT(IN) :: XCARBN
!
! !RETURN VALUE:
!
      REAL(fp)             :: FC_RO2HO2
!
! !REVISION HISTORY:
!  24 Jul 2014 - R. Yantosca - Now inlined to calcrate.F
!EOP
!------------------------------------------------------------------------------
!BOC

      FC_RO2HO2 = 1E+0_fp - EXP( -0.245E+0_fp * XCARBN )
     
    END FUNCTION FCRO2HO2
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: FyHORO
!
! !DESCRIPTION: \subsection*{Overview}
!  Function FYHORO returns returns the branching ratio between 
!  HOC2H4O oxidation and dissociation:
!  (1) HOC2H4 --O2--> HO2 + GLYC
!  (2) HOC2H4 ------> HO2 + 2CH2O
!
!\subsection*{References}
!  \begin{enumerate}
!  \item Orlando et al., 1998: \emph{Laboratory and theoretical study of the 
!         oxyradicals in the OH- and Cl-initiated oxidation of ethene}, 
!        \underline{J. Phys. Chem. A}, \textbf{102}, 8116-8123.
!  \item Orlando et al., 2003: \emph{The atmospheric chemistry of alkoxy 
!         radicals}, \underline{Chem. Rev.}, \textbf{103}, 4657-4689.
!  \end{enumerate}
!
! !INTERFACE: 
!
    FUNCTION FYHORO( ZDNUM, TT ) RESULT( FY_HORO )
!
! !INPUT PARAMETERS: 
!
      REAL(fp), INTENT(IN) :: ZDNUM   ! Air density   [molec/cm3 ]
      REAL(fp), INTENT(IN) :: TT      ! Temperature   [K         ]
!
! !RETURN VALUE:
!
      REAL(fp)             :: FY_HORO
!
! !REVISION HISTORY:
!  (1 ) Branching ratio calculation (tmf, 2/6/05).
!  20 Aug 2013 - R. Yantosca - Removed "define.h", this is now obsolete
!  25 Jul 2014 - R. Yantosca - Now inlined into calcrate.F
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      REAL(fp) :: K1, K2, O2DNUM

      !=================================================================
      ! FYHORO begins here!
      !=================================================================
      O2DNUM  = ZDNUM * 0.21E+0_fp
      K1      = 6.0E-14_fp * EXP(-550.E+0_fp/TT) * O2DNUM
      K2      = 9.5E+13_fp * EXP(-5988.E+0_fp/TT) 

      FY_HORO = K1 / (K1 + K2)
        
    END FUNCTION FYHORO
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: FyrNO3
!
! !DESCRIPTION: Function FYRNO3 returns organic nitrate yields 
!  YN = RKA/(RKA+RKB) from RO2+NO reactions as a function of the number 
!  N of carbon atoms.
!\\
!\\
! !INTERFACE:
!
    FUNCTION FYRNO3( XCARBN, ZDNUM, TT ) RESULT( FYR_NO3 )
!
! !INPUT PARAMETERS: 
!
      REAL(fp), INTENT(IN) :: XCARBN   ! Number of C atoms in RO2
      REAL(fp), INTENT(IN) :: ZDNUM    ! Air density   [molec/cm3 ]
      REAL(fp), INTENT(IN) :: TT       ! Temperature   [K         ]
!
! !RETURN VALUE:
!
      REAL(fp)             :: FYR_NO3 
! 
! !REVISION HISTORY: 
!  (1 ) Original code from Larry Horowitz, Jinyou Liang, Gerry Gardner,
!        and Daniel Jacob circa 1989/1990.
!  (2 ) Updated following Atkinson 1990.
!  (3 ) Change yield from Isoprene Nitrate (ISN2) from 0.44% to 12%,
!        according to Sprengnether et al., 2002. (amf, bmy, 1/7/02)
!  (4 ) Eliminate obsolete code from 1/02 (bmy, 2/27/02)
!  (5 ) Updated comment description of XCARBN (bmy, 6/26/03)
!  20 Aug 2013 - R. Yantosca - Removed "define.h", this is now obsolete
!  25 Jul 2014 - R. Yantosca - Now inlined into calcrate.F
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      REAL(fp) :: YYYN, XXYN,  AAA,  RARB, ZZYN
      REAL(fp) :: XF,   ALPHA, Y300, BETA, XMINF, XM0

      ! Initialize static variables
      DATA   Y300,ALPHA,BETA,XM0,XMINF,XF/.826,1.94E-22,.97,0.,8.1,.411/

      !=================================================================
      ! FYRNO3 begins here!
      !=================================================================
      XXYN    = ALPHA*EXP(BETA*XCARBN)*ZDNUM*((300./TT)**XM0)
      YYYN    = Y300*((300./TT)**XMINF)
      AAA     = LOG10(XXYN/YYYN)
      ZZYN    = 1./(1.+ AAA*AAA )
      RARB    = (XXYN/(1.+ (XXYN/YYYN)))*(XF**ZZYN)
      FYR_NO3 = RARB/(1. + RARB)
     
    END FUNCTION FYRNO3
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !ROUTINE: Arsl1k
!
! !DESCRIPTION: Function ARSL1K calculates the 1st-order loss rate of species 
!  on wet aerosol surface.
!\\
!\\
! !INTERFACE:
!
    FUNCTION ARSL1K( AREA, RADIUS, DENAIR, STKCF, STK, SQM ) &
         RESULT( ARS_L1K )
!
! !INPUT PARAMETERS: 
!
      ! Surface  area of wet aerosols/volume of air [cm2/cm3]
      REAL(fp), INTENT(IN) :: AREA     

      ! Radius of wet aerosol [cm], order of 0.01-10 um;
      ! Note that radius here is Rd, not Ro
      REAL(fp), INTENT(IN) :: RADIUS 
  
      ! Density of air [#/cm3]
      REAL(fp), INTENT(IN) :: DENAIR  
 
      ! Sticking coefficient [unitless], order of 0.1
      REAL(fp), INTENT(IN) :: STKCF  
  
      ! Square root of temperature [K]
      REAL(fp), INTENT(IN) :: STK  
    
      ! Square root of molecular weight [g/mole]
      REAL(fp), INTENT(IN) :: SQM      
!
! !RETURN VALUE:
!
      REAL(fp)             :: ARS_L1K
!
! !REMARKS:
!  The 1st-order loss rate on wet aerosol (Dentener's Thesis, p. 14)
!  is computed as:
!                                                                             .
!      ARSL1K [1/s] = area / [ radius/dfkg + 4./(stkcf * xmms) ]        
!                                                                             .
!  where XMMS = Mean molecular speed [cm/s] = sqrt(8R*TK/pi/M) for Maxwell 
!        DFKG = Gas phase diffusion coeff [cm2/s] (order of 0.1)

! !REVISION HISTORY:
!  01 Jul 1994 - lwh, jyl, gmg, djj - Initial version 
!  04 Apr 2003 - R. Yantosca - Updated comments, cosmetic changes
!  07 Apr 2004 - R. Yantosca - Now return w/ default value if RADIUS is zero 
!                              (i.e. is smaller than a very small number)
!  03 Dec 2009 - R. Yantosca - Prevent div-by-zero errors by returning the
!                              default value if any of the args are zero 
!  03 Dec 2009 - R. Yantosca - Added ProTeX Header
!  20 Aug 2013 - R. Yantosca - Removed "define.h", this is now obsolete
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      REAL(fp) :: DFKG

      !=================================================================
      ! ARSL1K begins here!
      !=================================================================
      IF ( AREA < 0e0_fp      .or. DENAIR < 1e-30_fp    .or.  & 
           RADIUS < 1e-30_fp  .or. SQM  < 1e-30_fp      .or.  &
           STK    < 1e-30_fp  .or.  STKCF  < 1e-30_fp ) THEN

         ! Use default value if any of the above values are zero
         ! This will prevent div-by-zero errors in the eqns below
         ! Value changed from 1d-3 to 1d-30 (bhh, jmao, eam, 7/18/2011)
         ARS_L1K = 1.E-30_fp

      ELSE

         ! DFKG = Gas phase diffusion coeff [cm2/s] (order of 0.1)
         DFKG  = 9.45E+17_fp/DENAIR * STK * SQRT(3.472E-2_fp + 1.E0_fp/ &
          (SQM*SQM))

         ! Compute ARSL1K according to the formula listed above
         ARS_L1K = AREA / ( RADIUS/DFKG + 2.749064E-4*SQM/(STKCF*STK) )

      ENDIF

    END FUNCTION ARSL1K
!EOC
!------------------------------------------------------------------------------
!                  GEOS-Chem Global Chemical Transport Model                  !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: Check_Nat
!
! !DESCRIPTION: Subroutine CHECK\_NAT determines whether the solid PSC is 
!  composed of ice or NAT (nitric acid trihydrate) (needed for heterogeneous
!  chemistry), or indeed if there is any direct PSC calculation at all. This
!  is important for determining whether to use the JPP or Kirner scheme for
!  ice cloud radii.
!\\
!\\
! !INTERFACE:
!
      SUBROUTINE CHECK_NAT( I, J, L, IS_NAT, IS_PSC, IS_STRAT, &
                            Input_Opt, State_Met, State_Chm )
!
! !INPUT PARAMETERS:
!
      INTEGER,        INTENT(IN)  :: I,J,L      ! Grid indices
      TYPE(OptInput), INTENT(IN)  :: Input_Opt  ! Input options
      TYPE(MetState), INTENT(IN)  :: State_Met  ! Meteorology State object
      TYPE(ChmState), INTENT(IN)  :: State_Chm  ! Chemistry State object
!
! !OUTPUT VARIABLES:
!
      LOGICAL,        INTENT(OUT) :: IS_NAT     ! Is surface NAT?
      LOGICAL,        INTENT(OUT) :: IS_PSC     ! Are there solid PSCs?
      LOGICAL,        INTENT(OUT) :: IS_STRAT   ! Are we in the strat?
!
! !REMARKS:
!  This routine is only activated for UCX-based mechanisms
!
! !REVISION HISTORY:
!  17 Apr 2013 - S. D. Eastham - Initial version
!  21 Feb 2014 - M. Sulprizio  - Now pass Input_Opt, State_Met, and State_Chm
!                                objects via the arg list
!  08 Apr 2015 - R. Yantosca   - Remove call to READ_PSC_FILE, this is
!                                now done from DO_CHEMISTRY (chemistry_mod.F)
!  29 Jan 2016 - M. Sulprizio  - Moved this routine from ucx_mod.F to
!                                gckpp_HetRates.F90
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
      LOGICAL :: IS_TROP

      !=================================================================
      ! CHECK_NAT begins here!
      !=================================================================

      ! Check if box is in the troposphere
      IS_TROP  = ( State_Met%PEDGE(I,J,L) > State_Met%TROPP(I,J) )

      ! Check if box is in the stratosphere
      IS_STRAT = ( ( L .le. LLSTRAT ) .and. ( .not. IS_TROP) )

      ! Check if there are solid PSCs
      IS_PSC   = ( ( Input_Opt%LPSCCHEM ) .and. &
                 ( State_Chm%STATE_PSC(I,J,L) >= 2.0 ) .and. ( IS_STRAT ) )

      ! Check if there is surface NAT
      IS_NAT   = ( ( IS_PSC ) .and. ( SPC_NIT .gt. TINY(1e+0_fp) ) )

    END SUBROUTINE CHECK_NAT
!EOC
  END MODULE GCKPP_HETRATES
